設計模式(四)std::function介面程式設計徹底取代抽象工廠和工廠方法

CalmReason發表於2016-03-16

 

抽象工廠Abstract Factory

意圖:用工廠類的不同成員函式來返回不同型別的物件。這些不同的物件往往是有著共同的基類,最終是想利用多型。而多型已經被function+bind取代,所以這個模式沒啥意義!

 

特點:使用智慧指標獲取物件,而不是暴露原始指標。

程式碼:

 

#include "boost/smart_ptr.hpp"
#include "boost/weak_ptr.hpp"

#include<iostream>
using namespace std;
using namespace boost;
//介面類
class Base
{
public:
	//抽象基類
	virtual void f(void) = 0;//介面函式
	virtual void g(void) = 0;//介面函式
protected:
	//只有派生類才可以建立基類物件
	Base(){cout<<"Base()"<<endl;}
	~Base(){cout<<"~Base()"<<endl;}
};
class A : public Base
{
public:
	A(void){cout<<"A()"<<endl;}
	~A(void){cout<<"~A()"<<endl;}
	void f(void) {cout<<"A::f()"<<endl;}
	void g(void) {cout<<"A::g()"<<endl;}
};
class B : public Base
{
public:
	B(void){cout<<"B()"<<endl;}
	~B(void){cout<<"~B()"<<endl;}
	void f(void) {cout<<"B::f()"<<endl;}
	void g(void) {cout<<"B::g()"<<endl;}
};
//各種物件建立的統一入口,而不是全域性的多個公開函式
class Factory
{
public:
	static boost::shared_ptr<Base> CreateA(void)
	{
		return boost::make_shared<A>();
	};
	static boost::shared_ptr<Base> CreateB(void)
	{
		return boost::make_shared<B>();
	}; 
};

int main(int,char**)
{

	boost::shared_ptr<Base> pbase = Factory::CreateA();
	pbase->f();
	pbase->g();
	//引用計數為0自動釋放物件
	pbase = Factory::CreateB();
	pbase->f();
	pbase->g();

	return 0;
};

 

 

 

工廠方法Factory Method

意圖:定義一個建立物件的介面,讓子類決定例項化哪一個類,意圖同抽象工廠一樣想使用多型,所以這個模式也是多餘的,使用function+bind即可。
這個模式就是想突破抽象工廠修改原始碼的問題。使用C++模板就可以輕鬆實現。

 

程式碼:

 

#include "boost/smart_ptr.hpp"
#include "boost/weak_ptr.hpp"

#include<iostream>
using namespace std;
using namespace boost;
//介面類
class Base
{
public:
	//抽象基類
	virtual void f(void) = 0;//介面函式
	virtual void g(void) = 0;//介面函式
protected:
	//只有派生類才可以建立基類物件
	Base(){cout<<"Base()"<<endl;}
	~Base(){cout<<"~Base()"<<endl;}
};
class A : public Base
{
public:
	A(void){cout<<"A()"<<endl;}
	~A(void){cout<<"~A()"<<endl;}
	void f(void) {cout<<"A::f()"<<endl;}
	void g(void) {cout<<"A::g()"<<endl;}
};
class B : public Base
{
public:
	B(void){cout<<"B()"<<endl;}
	~B(void){cout<<"~B()"<<endl;}
	void f(void) {cout<<"B::f()"<<endl;}
	void g(void) {cout<<"B::g()"<<endl;}
};
//新增新類不需要修改原來的程式碼
template<typename T>
class Factory
{
public:
	static boost::shared_ptr<T> Creator(void)
	{
		return boost::make_shared<T>();
	};
};

int main(int,char**)
{

	boost::shared_ptr<Base> pbase = Factory<A>::Creator();
	pbase->f();
	pbase->g();
	//引用計數為0自動釋放物件
	pbase = Factory<B>::Creator();
	pbase->f();
	pbase->g();

	return 0;
};

 

 

 

面向介面程式設計

object-based

上面的程式無非是想呼叫不同的void fun(void)函式,那麼更一般的,抽象介面類應該是一些函式的集合。函式可以隨意指定,拼裝。

 

使用function+bind應該像下面這樣:

程式碼:

 

#include <functional>
#include <memory>
#include<iostream>
using namespace std;
#include "boost/noncopyable.hpp"

class A 
{
public:
	A(void){cout<<"A()"<<endl;}
	~A(void){cout<<"~A()"<<endl;}
	void f(void) {cout<<"A::f()"<<endl;}
	void g(void) {cout<<"A::g()"<<endl;}
};
class B 
{
public:
	B(void){cout<<"B()"<<endl;}
	~B(void){cout<<"~B()"<<endl;}
	void f(void) {cout<<"B::f()"<<endl;}
	void g(void) {cout<<"B::g()"<<endl;}
};

class InterfaceBase : public boost::noncopyable
{
	typedef function<void(void)> f_callback;
	typedef function<void(void)> g_callback;
public:
	InterfaceBase(f_callback f1,g_callback g1)
		:f(f1)
		,g(g1)
	{}
public:
	f_callback f;
	g_callback g;
};

int main(int,char**)
{
	A a;
	InterfaceBase ibase(
		bind(&A::f,&a)
		,bind(&A::g,&a)
		);
	ibase.f();
	ibase.g();

	B b;
	//注意這裡沒有多型,沒有指標,沒有虛擬函式,沒有二進位制相容問題
	InterfaceBase ibase1(
		bind(&B::f,&b)
		,bind(&B::g,&b)
		);
	ibase1.f();
	ibase1.g();

	return 0;
};


 

 

 

 

 

 

相關文章