AbstarctFactory模式——设计模式学习

  Abstract Factory 模式

一 意图

  提供一个创建一系列相关或相互依赖对象的接口,而无需制定他们具体的类。

二 逻辑

  抽象工厂模式中的4中不同角色:

1 抽象工厂(Abstract Factory):

  它与应用系统商业逻辑无关。

2 具体工厂(Concrete Factory):

  这个角色直接在客户端的调用下创建产品的实例。

  这个角色含有选择合适的产品对象的逻辑,而这个逻辑是与应用系统的商业逻辑紧密相关的。

3 抽象产品(Abstract Product):

  担任这个角色的类是工厂方法模式所创建的对象的父类,或它们共同拥有的接口。

4 具体产品(Concrete Product):

  抽象工厂模式所创建的任何产品对象都是某一个具体产品类的实例。

  这是客户端最终需要的东西,其内部一定充满了应用系统的商业逻辑。

三 结构图

  此图我是看了很久,感觉非常困惑:

  抽象工厂的意图是提供一个创建一系列相关或相互依赖对象的接口,

  而无需制定他们具体的类。

根据图中所描述的。

问题:

  1 一个接口:是指AbstractFctory还是所提供的方法:

    CreateProductA(), CreateProductB()(这两个接口)

  2 创建一系列对象:

    CreateProductA(), CreateProductB(),这一系列对象之间要有什么关系吗?

  3 相关或相互依赖:图中并没有体现出来怎么相关或者依赖?

  4 创建一系列对象怎么使用:

    直接给Client单独使用还是组合之后给Client使用,并没有交代清楚。

    图中为何Client指向AbstractProductA和AbstractProductB这两个类,

    既然是创建一系列对象,这一系列对象应该和这两个类是什么关系?

  5 无需制定他们具体的类:图中明显提到了ProdcutA1和ProductB1等?

  6 AbstractFactory是抽象类,是否所有的方法都是纯虚函数?

    AbstractFactory类提供了全面的一系列创建对象的方法,它的派生类ConcreateFactory1,

    是否是需要将AbstractFactory类的所有方法实现?(如果都是纯虚函数,那必然是)

  7 AbstractFactory提供了创建对象 obj1,obj2,obj3,obj4,……等方法(非纯虚的),

    ConcreateFactory1实现其中的obj1,obj2,obj3创建方法,

    ConcreateFactory2实现了其中的obj2,obj3,obj4创建方法,这样的工厂是否有必要存在?

看了之后所给的maze游戏的maze创建方法之后才有所明白有些问题。

想法:

  1 一个接口:AbstractFctory抽象类

  2 CreateProductA(), CreateProductB()必然是相关或者相互依赖的关系对象,需要被组合起来使用。

  3 相关或相互依赖:Client使用接口创建一系列对象之后,自己确定这对象之间的应用关系。

  4 创建一系列对象怎么使用:由Client确定如何使用。

    创建一系列相关或相互依赖的对象之后,利用其之间的关系需要将其组合成一个独立的对象来使用(最好如此),

    这样工厂创建的一系列对象具有完整性,可以很好的再被封装起来。

  5 无需制定他们具体的类:

    在具体的工厂类提供的创建对象的方法ConcreateProductA()中制定具体的产品类的,

    而对于Client而言,是不能知道的,仅知道抽象的产品产品类。

  6 AbstractFactory作为抽象类,

    提供了创建对象的统一的一系列方法,都是同一个层次上,

    是不能确定那一个为纯虚函数而另一个不是纯虚函数,

    所以AbstractFactory所有方法必然都纯虚函数(理论上认为)。

  7 既然都是纯虚函数,都必须实现所有的方法。

    如果只需要其中某几个对象,那么可以在Client创建需要的对象。

    这样看似更加灵活,实则违背了AbstractFactory模式中:创建一系列相关或相互依赖对象。

    创建的一系列对象尽量使其具有相关或相依赖。但是这在实际情况中是有需求的。

  8 解决上述问题的方法之一:

    将工厂AbstractFactory不必定义为抽象类,

    将构造函数属性设为private,同样是不可以创建对象的,

    而其派生类可以根据合适的需要来实现相应的方法。这算是AbstactFactory的一个变种。

为什么必然是相关或者相互依赖?

  Client使用一个接口创建一系列对象,而如果这些对象之间的关联性很小,

  那么就不会抽象这样一个工厂类,就不可能产生这样一个模式,违反类的设计原则。

相关或相互依赖的对象应该具体是怎么样的一种相关或相依赖?

  具体要怎么一种相关这个我感觉不大容易说清楚。相关相依赖本身就是比较抽象的说法,只能具体问题具体对待。

  在书中所设计maze游戏中,创建一系列对象:Maze,Wall,Room,Door等,之间关系是非常的密切。

四 代码实现

1 产品类

基类 Frame,派生类Title,Menu,Toolbar,Page及其各自相关的派生类

View Code Product
/***********************************************
* Class Frame *
*********************************************
*/
class Frame
{
public:
virtual void draw() = 0;
};

/***********************************************
* Class Title *
*********************************************
*/
class Title : public Frame
{
public:
virtual void draw()
{
cout<<"title draw"<<endl;
}
};

class TextTitle: public Title
{
public:
virtual void draw()
{
cout<<"TextTitle draw"<<endl;
}
};

class ImageTitle: public Title
{
public:
virtual void draw()
{
cout<<"ImageTitle draw"<<endl;
}
};

/***********************************************
* Class Menu *
*********************************************
*/
class Menu : public Frame
{
public:
virtual void draw()
{
cout<<"menu draw"<<endl;
}
};

class ListMenu: public Menu
{
public:
virtual void draw()
{
cout<<"ListMenu draw"<<endl;
}
};

class ThreeDMenu: public Menu
{
public:
virtual void draw()
{
cout<<"3DMenu draw"<<endl;
}
};

/***********************************************
* Class Toolbar *
*********************************************
*/
class Toolbar : public Frame
{
public:
virtual void draw()
{
cout<<"Toolbar draw"<<endl;
}
};

class CellToolbar : public Toolbar
{
public:
virtual void draw()
{
cout<<"CellToolbar draw"<<endl;
}
};

class FloatToolbar : public Toolbar
{
public:
virtual void draw()
{
cout<<"CellToolbar draw"<<endl;
}
};

/***********************************************
* Class Page *
*********************************************
*/
class Page : public Frame
{
public:
#define FRAME_MAX 10

Page()
{
m_frame_num = 0;
}

void AddFrame(Frame* frm)
{
if (m_frame_num < FRAME_MAX)
{
m_frame[m_frame_num] = frm;
m_frame_num++;
}
}
virtual void draw()
{
cout<<"page draw"<<endl;
for (int i =0; i < m_frame_num; i++)
{
m_frame[i]->draw();
}
}
private:
Frame* m_frame[FRAME_MAX];
int m_frame_num;
};

class SlidePage : public Page
{
public:
virtual void draw()
{
Page::draw();
cout<<"SlidePage draw"<<endl;
}
};

class VaryPage : public Page
{
public:
virtual void draw()
{
Page::draw();
cout<<"VaryPage draw"<<endl;
}
};


2 工厂类

抽象基类ControlFactory  派生类GeneralControl,DazzlingControl

View Code Factory
/***********************************************
* Class controlFactory *
*********************************************
*/

class ControlFactory
{
public:
virtual Title* CreateTitle() = 0;
virtual Menu* CreateMenu() = 0;
virtual Toolbar* CreateToolBar() = 0;
virtual Page* CreatePage() = 0;
};

class GeneralControl:ControlFactory
{
public:
virtual Title* CreateTitle()
{
return new TextTitle();
}
virtual Menu* CreateMenu()
{
return new ListMenu();
}
virtual Toolbar* CreateToolBar()
{
return new CellToolbar();
}
virtual Page* CreatePage()
{
return new SlidePage();
}
};

class DazzlingControl:ControlFactory
{
public:
virtual Title* CreateTitle()
{
return new ImageTitle();
}
virtual Menu* CreateMenu()
{
return new ThreeDMenu();
}
virtual Toolbar* CreateToolBar()
{
return new FloatToolbar();
}
virtual Page* CreatePage()
{
return new VaryPage();
}
};

3 Client

View Code Client
bool ShowPage(Page* pg)
{
pg->draw();

return true;
}

int main()
{
//创建ControlFactory控件工厂类
ControlFactory* factory = (ControlFactory*) new GeneralControl();

//创建一系列相关的控件
Page* pg = factory->CreatePage();
Title* tl = (Title*)factory->CreateTitle();
Menu* mu = (Menu*)factory->CreateMenu();
Toolbar* tb = (Toolbar*)factory->CreateToolBar();

//将控件加入到Page中
pg->AddFrame((Frame*)tl);
pg->AddFrame((Frame*)mu);
pg->AddFrame((Frame*)tb);

//显示Page
ShowPage(pg);

return 0;
}


4 输出结果

page     draw
TextTitle   draw
ListMenu   draw
CellToolbar    draw
SlidePage      draw


五 实例分析

工作之中其实发现对这个模式的应用并不多(和工作内容可能有些关系),

在一个系列的产品中各个组成构件基本上一致,

或者之间存在着构件之间的很大差异性,你有的我没有我有别的。

下面看几个实例:

对于VappMsgDialogCell不同系列的产品,其中的差别是比较小的而且又相似,

仅需要更改其中的某个就可以了,而大多数情况都是如此类型的。

如果使用AbstactFactory模式,对于一个很小差别却要重新创建所有的一系列产品,

增加好几个类,容易使代码变得冗余,不利于代码的重用。

但是对于AbstactFactory模式我感觉良好,它能保证我一次性关注的东西降到最少而且纯粹,

因为相对于代码重用,我更喜欢分开搞,

很多东西放在一起容易出错逻辑复杂,

一次性需要关注的东西太多,脑袋忙不过来(智商太低)。

但是在这个重构,复用满天飞的环境里面,这种想法只能是必须抛弃的。


六 分析总结

优点:

1 封装了具体类的实现

  AbstarctFactory工厂类封装了产品的创建过程,

  使Client不必去关心具体产品对象的创建实现过程。

2 具有整体的一致性

   使用任何一个具体的工厂类,创建的是一系列相关或者相互依赖的产品对象,

  客户端关注一些列相关的对象,降低复杂性,一次应用是一个整体。

3 灵活便于更改

   一次应用创建的是一系列特定的相关的产品对象,当需要更换产品时,

  只需要更改具体的创建工厂,改变变得很容易和迅速。

缺点:

1 不宜扩展

  当一些列产品中某个组成构件需要变化时,

  则需要重新设计新的产品类和创建新的工厂类。

  当需要增加系列对象的组成构件时则需要更改AbstactFactory所有相关的类。

2 Client处理复杂

  Client面对的是一些列的对象,

  需要自己去合理的处理这些对象之间的关系,

  而不是作为一个完整封装起来的整体对象。

重点:

1 系列产品的设计

  确定相对稳定系列相关的产品和创建工厂类,

  而且系列对象具有整体的可变性,封装的变化以达到产品迅速替换。

2 产品之间关系的确定

  产品之间必然存在着相关或者相互依赖的关系,

  而且显式的体现出来,使用工厂类创建一系列对象,

  对象之间关系既要本身独立又要在某方面关联性很强。

原文地址:https://www.cnblogs.com/bastard/p/2253107.html