Abstract Factory,Factory Method,Prototype。它们都是Creationall
Patterns,它们的关系如下图所示:
----------------------------------Abstract
Factory----------------------------
●Tip 1:关键字。Family。
●Tip 2:图。书中的原图如下,
我又画了一张,主要是为我后边讨论本模式“支持变化”做准备,
可以看到,Client用了一个Factory,一个Factory可以“生产”一个Product
Family(就是多个Product或A Set of Products),Client使用这一个Product
Family。
●Tip 3:实现和使用。
从图中可以看到,ConcreteFactory负责实例化ConcreteProduct,但谁来实例化ConcreteFactory呢?图中Client
Class仅对AbstractFactory有关联,但是一个Client Class是不能拥有一个Interface的实例的,而只能拥有它的指针或引用(来支持多态);那么Client
Class能new AbstractFactory吗,不仅不能,而且要new
ConcreteFactory才对呀。
结论,当“Architect或Achitecture工程师”“实现”Abstract
Factory模式时,ConcreteProduct的实例化问题已经考虑在内了,因为这恰恰就是该模式的使命。而当“Application工程师”“使用”Abstract
Factory模式时,应负责实例化ConcreteFactory。
在ET++中,Abstract Factory模式实现得非常巧妙。具体实例化哪个ConcreteFactory是“Architect或Achitecture工程师”写在Framework中的一些If语句决定的,这些If语句去读环境变量,解除了“Application工程师”去实例化ConcreteFactory的职责。ET++中的WindowSystem的相关研究,请参考本站(lcspace.nease.net)的Framework栏目。
在MFC中,CDocTemplate也是Abstract Factory模式,并且也非常巧妙地用CRumtimeClass机构解决具体实例化哪个ConcreteFactory的问题。
●Tip 4:支持变化。It makes exchanging product families easy。
不同Product Family一般用于支持类似“多种平台”这样的情形(所以Client一般不同时使用多个Product
Family)。想像“Application工程师”欲将Client移植到新平台,由于Client
Class对AbstractProduct和AbstractFactory是“良性依赖”(在图中用绿色标出),所以不会引起Client
Class的代码变动。如果Client Class还负责“实例化ConcreteProduct”,那么只需改区区2处,比如从
#include "BombedMazeFacory.h"
BombedMazeFacory factory;
game.CreateMaze( factory );
改变成
#include "AnotherMazeFacory.h" //changed
AnotherMazeFacory factory; //changed
game.CreateMaze( factory );
增加新的Product
Family,对“Architect或Achitecture工程师”来说,只需新写图中黄色Class:新写了一个New
ConcreteFactory以及它生产的New Product Family。
在MFC中,CFrame/CDocument/CView就是一个Product Family,我们的确很容易地创建New
Product Fameliy:CMyFrame/CMyDoc/CMyView。
●Tip 5:局限性。Supporting new kinds of products is difficult。
简单说,就是将“支持这6个Product”换成“支持那6个Product”容易,换成“支持那7个Product”难。因为AbstractFactory的操作的个数和Product
Family中Product的个数相对应,它限制了所有ConcreteFactory的接口,这个接口不应也不易随便改。在图中表现得很充份,Client可以有多个,AbstractProduct可以有多个,Product
Family可以有多个,ConcreteFactory可以有多个,唯独AbstractFactory只有一个。
在MFC中,CFrame/CDocument/CView就是一个Product
Family,你想在Doc/View arch下创建一个4员组,难。
----------------------------------Factory
Method----------------------------
●Tip 1:关键字。Subclass,Virtual,Override。
●Tip 2:图。
●Tip 3:实现和使用。
A factory method define an interface for creating an object,它只要求该Method的责任是Factory:你可以将它实现成纯虚函数/空函数/做相关创建的函数,用于不同情况。但是,在C++中它总是虚函数。
在MFC中,CWnd::Create()就是典型的例子。
●Tip 4:支持变化。
可以看到,2个基类Superclass和AbstractProduct是Framework的组成部份,并且Superclass对AbstractProduct是“对接口编程”,所以是“良性依赖”(在图中用绿色标出),不易引起Superclass的代码变动。
图中黄色的类是New Application新加的,Subclass2对Product2是“恶性依赖”(在图中用红色标出),但又有什么关系呢?因为它们都属于Application,而且Subclass2::FactoryMethod()仅仅创建Product2,涉及的代码很少。
●Tip 5:支持框架。Factory methods pervade toolkits and
frameworks。The framework must instantiate classes, but it only
knows about abstract classes, which it cannot instantiate。Factory
methods eliminate the need to bind application-specific classes into
your code。A factory method define an interface for creating an
object, but let subclasses CAN (may not) decide which class to
instantiate。
----------------------------------Prototype----------------------------
●Tip 1:关键字。Copy,Clone itself。
●Tip 2:图。
●Tip 3:实现和使用。
Wall * BombedWall::Clone() const
{
return new BombedWall( *this );
}
在MFC中,CWnd::Create()就是典型的例子。
●Tip 4:优点。
仅有 1 个“类层次”,而不是象Factory Method一样平行的
2 个。
----------------------------------Abstract Factory,Factory Method,Prototype,Template
Method----------------------------
●Tip 1:下面是2种典型的应用情况(其中使用Abstract
Factory的情况又分2种实现):
可以看到,Abstract Factory模式常要使用Factroy
Method模式或者Prototype模式,Template Method经常调用Factroy
Method,
●Tip 2:Abstract
Factory模式使用Factroy Method模式之例──使用Abstract
Factory的MazeGame。注意MazeFactory已内置缺省实现故不是AbstractMazeFactory;还要注意哪里是“对接口编程”,哪里是“对子类名硬编码”。
/////////////////////////////////////////////////////AbstractFactory
#include "Maze.h"
#include "Room.h"
#include "Wall.h"
class MazeFactory //a superclass as a AbstractFactory, but not containing pure virtual method
{
public:
MazeFactory(); //con
virtual Maze* MakeMaze() //a factory method, which must be virtual
{return new Maze;}
virtual Room * MakeRoom(int n) //a factory method, which must be virtual
{return new Room(n);}
virtrul Wall * MakeWall() //a factory method, which must be virtual
{return new Wall;}
};
/////////////////////////////////////////////////////Client
#include "BombedMazeFacory.h" //这里是对子类名硬编码(类名和文件名一样)
void MazeGame::XXXXXXXX ( void )
{
BombedMazeFacory factory; //实例化ConcreteFactory,这里是对子类名硬编码
CreateMaze( factory );
}
Maze* MazeGame::CreateMaze (MazeFactory & factory) //BombedMazeFacory.h must
// have included MazeFactory.h, so MazeFactory is available
{
//
//these 4 statements call Factory to create some Products
//这里是对接口编程
//
Maze* aMaze = factory.MakeMaze();
Room* r1 = factory.MakeRoom(1);
Room* r2 = factory.MakeRoom(2);
Door* aDoor = factory.MakeDoor(r1, r2);
//
//all the rest statements use these Products
//这里是对接口编程
//
aMaze->AddRoom(r1);
aMaze->AddRoom(r2);
r1->SetSide(North, factory.MakeWall());
r1->SetSide(East, aDoor);
r1->SetSide(South, factory.MakeWall());
r1->SetSide(West, factory.MakeWall());
r2->SetSide(North, factory.MakeWall());
r2->SetSide(East, factory.MakeWall());
r2->SetSide(South, factory.MakeWall());
r2->SetSide(West, aDoor);
return aMaze;
}
/////////////////////////////////////////////////////ConcreteFactory
#include "MazeFactory.h"
#include "BombedMaze.h"
class BombedMazeFactory : public MazeFactory //a subclass as a ConcreteFactory
{
public:
BombedMazeFactory();
virtual Maze* MakeMaze() //override a factory method, which must be virtual
{return new BombedMaze;}
};
●Tip 3:Template
Method经常调用Factroy Method之例──使用Template Method的MazeGame。注意与使用Abstract
Factory的MazeGame比较。
/////////////////////////////////////////////////////Superclass
class MazeGame
{
public:
MazeGame(); //con
Maze* CreateMaze(); //a Template Method
virtual Maze* MakeMaze();//4 factory methods, which must be virtual
virtual Room* MakeRoom(int n);
virtual Wall* MakeWall() const
virtual Door* MakeDoor(Room* r1, Room* r2);
};
/////////////////////////////////////////////////////Template Method
Maze* MazeGame::CreateMaze ()
{
//
//本模板方法调用工厂方法MakeXxx()
//
Maze* aMaze = MakeMaze();
Room* r1 = MakeRoom(1);
Room* r2 = MakeRoom(2);
Door* theDoor = MakeDoor(r1, r2);
aMaze->AddRoom(r1);
aMaze->AddRoom(r2);
r1->SetSide(North, MakeWall());
r1->SetSide(East, theDoor);
r1->SetSide(South, MakeWall());
r1->SetSide(West, MakeWall());
r2->SetSide(North, MakeWall());
r2->SetSide(East, MakeWall());
r2->SetSide(South, MakeWall());
r2->SetSide(West, theDoor);
return aMaze;
}
/////////////////////////////////////////////////////Subclass
#include "MazeGame.h"
#include "BombedWall.h"
#include "RoomWithABomb.h"
class BombedMazeGame : public MazeGame
{
public:
BombedMazeGame(); //con
virtual Wall* MakeWall() //override a factory method, which must be virtual
{ return new BombedWall; }
virtual Room* MakeRoom(int n) //override a factory method, which must be virtual
{ return new RoomWithABomb(n); }
};
上一页 下一页
|
|