设计模式:创建型模式

抽象工厂 abstract factory

例子

考虑一个多风格的界面应用,要求可以切换不同风格类型的组件(窗口,滚动条,按钮等)
设计模式:创建型模式_第1张图片

风格/组件 pm风格 motif风格
滚动条 pmScrollBar motifScrollBar
窗口 pmWindow MotifWindow

WidgetFactory: 抽象工厂,用于创建滚动条和窗口。

MotifWidgetFactory: 继承抽象工厂(WidgetFactory),用于给Motif类型创建滚动条和窗口。
他依赖于MotifWindow和MotifScrollBar

PMWidgetFactory: 继承抽象工厂(WidgetFactory),用于给PM类型创建滚动条和窗口。
他依赖于PMWindow和PMScrollBar

Client: 客户端,用来操作软件或者系统

结构

设计模式:创建型模式_第2张图片
设计模式:创建型模式_第3张图片

builder 模式

例子

支持多种格式的富文本阅读器(RTF),比如tex文本,ASCII, WIDGET
设计模式:创建型模式_第4张图片
客户端解析文本时,先选择builder,然后根据文本流不同类型,转换不同成不同的格式
比如:tex格式支持复杂的数学公式,只有texbuilder有这个分支

结构

设计模式:创建型模式_第5张图片

  1. Builder (TextConverter) 建造者
    specifies an abstract interface for creating parts of a Product object. (为了创建一个对象或者对象的部分而指定一个抽象接口)
  2. ConcreteBuilder (ASCIIConverter, TeXConverter, TextWidgetConverter) 具体建造者
    constructs and assembles parts of the product by implementing the Builder interface. (通过实现建造接口来构建一个产品或者产品的部分)
    defines and keeps track of the representation it creates. (定义并跟踪所创建的表现方式)
    provides an interface for retrieving the product (e.g., GetASCIIText, GetTextWidget). (提供一个获取产品的接口)
  3. Director (RTFReader) 指挥者
    constructs an object using the Builder interface. (用建造接口创建一个对象)
  4. Product (ASCIIText, TeXText, TextWidget) 产品
    represents the complex object under construction. (表示一个正在构建的复杂对象)ConcreteBuilder builds the product’s internal representation and defines the process by which it’s assembled. (具体的建造者构建产品的内部展示,并定义了产品的组装过程)
    includes classes that define the constituent parts (包含构成产品的部件), including interfaces for assembling the parts into the final result. (包含将部件组成最终结果的接口)
    设计模式:创建型模式_第6张图片

factory method 工厂方法

未完待续

对比

背景:设计一个迷宫,仅考虑迷宫的构成:由一系列房间,墙,门组成。房间知道邻居是谁:房间,墙或者门。门连接两个房间。忽略所有和游戏者相关的操作:移动,显示等。

定义方向:enum Direction {North,South, East, West}

迷宫组件公共抽象类 MapSite
设计模式:创建型模式_第7张图片

不使用设计模式

Class MapSite
{
    public:
        virtual void Enter()=0;
};

class Room : public MapSite { 
	public : 
		Room (int roomNo) 
		MapSite* GetSide (Direction) const; 
		void SetSide (Direction, Mapsite*); 
		virtual void Enter() 
	private: 
		MapSite* _sides[4] ; 
		int _roomNumber; 
};

class Wall : public MapSite { 
	public : 
		Wall();
		virtual void Enter( ) ;
};
class Door public Mapsite { 
	public : 
		Door (Room* = 0, Room* = 0) ; 
		virtual void Enter ( ) 
		Room* OtherSideFrom (Room* ) ;
	
	private :
		Room* _room1;
		Room* _room2;
		bool _isOpen ; 
} ;

class Maze 
{
	Public:
		Maze ; 
		void AddRoom (Room* ) ; 
		Room* RoomNo ( int) const ; 
	private: 
//…
};


//创建迷宫 
Maze *MazeGame()
{
	Maze* aMaze =new Maze;
	Room *r1 = new Room(1);
	Room *r2 = new Room(2);
	Door theDoor = new Door(r1,r2);
	aMaze ->AddRoom(r1);
	aMaze ->AddRoom(r2);
	r1->SetSide(North, new Wall);
	r1->SetSide(South, theDoor );
	r1->SetSide(East,  new Wall);
	r1->SetSide(West, new Wall);
	r2 ->SetSide(North, new Wall);
	r2 ->SetSide(South,  new Wall);
	r2 ->SetSide(East,  new Wall);
	r2 ->SetSide(West, theDoor );
	return aMaze;
}

抽象工厂


 class MazeFactory ( 
public
	MazeFactory ( ) ; 
	virtual Maze* MakeMaze() const 
	{return new Maze; }
	virtual Wall* MakeWall() const 
	{return new Wall; }
	virtual Room* MakeRoom(int n) const 
	{return new Room(n)} )
	virtual Door* MakeDoor ( Room* r1, Room* r2)  const
	{return new Door (rl, r2); }
}

 class BombedMazeFactory  : public MazeFactory( 
public
	BombedMazeFactory ( ) ; 
	virtual Maze* MakeMaze() const 
	{return new Maze; }
	virtual Wall* MakeWall() const 
	{return new BombedWall; }
	virtual Room* MakeRoom(int n) const 
	{return new BombedRoom(n)} )
	virtual Door* MakeDoor ( Room* r1, Room* r2)  const
	{return new BombedDoor (rl, r2); }
}


Maze *MazeGame:: CreateMaze(MazeFactory & factory)
{
	Maze* aMaze =factory. MakeMaze() ;
	Room *r1 = factory. MakeRoom(1) ;
	Room *r2 =factory. MakeRoom(2) ;
	Door theDoor = factory.MakeDoor(r1,r2);
	aMaze ->AddRoom(r1);
	aMaze ->AddRoom(r2);
	r1->SetSide(North, factory.MakeWall() );
	r1->SetSide(South, theDoor );
	r1->SetSide(East,   factory.MakeWall() );
	r1->SetSide(West,  factory.MakeWall() );
	r2 ->SetSide(North,  factory.MakeWall() );
	r2 ->SetSide(South,   factory.MakeWall() );
	r2 ->SetSide(East,   factory.MakeWall() );
	r2 ->SetSide(West, theDoor );
	return aMaze;
}


builder

Builder 模式

class MazeBuilder { 
	public: 
		virtual void BuildMaze (){}
		virtual void BuildRoom (int room) { } 
		virtual void BuildDoor (int roomFrom. int roomTo ) { } 
		virtual Maze* GetMaze () { return 0 ; } 
	protectedMazeBuiIder();
};

该 接 口 可 以 创 建 : 1 ) 迷 宫 。 2 ) 有 一 个 特 定 房 间 号 的 房 间 。 3 ) 在 有 号 码 的 房 间 之 间 的 门 。
GetMaze 操 作 返 回 这 个 迷 宫 给 客 户 。 MazeBu11der 的 子 类 将 重 定 义 这 些 操 作 , 返 回 它 们 所 创 建
的 迷 宫 。

不定义为纯虚函数,是为了方便派生类只重定义它们感兴趣的接口

用 MazeBuilder 接 口 , 我 们 可 以 改 变 createMaze 成 员 函 数 , 以 生 成 器 作 为 它 的 参 数 。

Maze* MazeGame ::CreateMaze (MazeBuilder & builder)
 { 
	builder.BuildMaze(); 
	builder.BuildRoom(1); 
	builder.BuildRoom(2); 
	builder.BuildDoor(1,2) ;
	return builder.GetMaze()}

将 这 个 createMaze 版 本 与 原 来 的 相 比 , 注 意 生 成 器 是 如 何 隐 藏 迷 宫 的 内 部 表 示 的 一 一 一 即 定
义 房 间 、 门 和 墙 壁 的 那 些 类 . 一 一 以 及 这 些 部 件 是 如 何 组 装 成 最 终 的 迷 宫 的 。 有 人 可 能 猜 测 到
有 一 些 类 是 用 来 表 示 房 间 和 门 的 , 但 没 有 迹 象 显 示 哪 个 类 是 用 来 表 示 墻 壁 的 。 这 就 使 得 改 变
一 个 迷 宫 的 表 示 方 式 要 容 易 一 些 , 因 为 所 有 MazeBuiIder 的 客 户 都 不 需 要 被 改 变 。

MazeBuilder自己并不创建迷宫,子 类 做 实 际 工 作:
子 类 StandardMazeBuilder :一 个 创 建 简 单 迷 宫 的 实 现 。 它 将 它 正 在 创 建 的 迷 宫 放 在 变 量 _currentMaze 中 。

class StandardMazeBuiIder : public MazeBuilder
{ 
	Public:
		StandardMazeBuilder(){ _currentMaze=0}; 
		virtual void BuildMaze (){  _currentMaze = new Maze;}
		virtual void BuildRoom (int room) { } 
		virtual void BuildDoor (int roomFrom. int roomTo ) { } 
		virtual Maze* GetMaze ()return _currentMaze; } 
	Private:
		Direction CommonWall( room*, Room*);
		 Maze* _currentMaze;
}

//创造一个都是墙的房间
void StandardMazeBuilder :: BuildRoom (int n) 
{
	if (! _currentMaze—>RoomNo (n)) 
	{ 
		Room room =new Room(n);
		 _currentMaze->AddRoom(room); 
		room->SetSide (North, new  Wall); 
		room->SetSide(South, new Wall); 
		room->SetSide(East, new Wall);  
		room->SetSide(West, nev Wall);
	}
}

//建造一扇两个房间之间的门,其中CommonWall找到两个房间相邻的墙壁
Void StandardMazeBuilder::BuildDoor(int n1, int n2)
{
	Room* r1 =  _currentMaze->RoomNo(n1);
	Room* r2 =  _currentMaze->RoomNo(n2);
	Door *d = new Door(r1,r2);
	r1->SetSide(CommonWall(r1,r2) , d);
	r1->SetSide(CommonWall(r2,r1) , d);
}
现在客户可以创建迷宫了
Maze* maze; 
MazeGame game; 
StandardMazeBuiIder builder ; 
game. CreateMaze (builder) 
Maze= builder.GetMaze(); 

我 们 本 可 以 将 所 有 的 standardMazeBuiIderN 作 放 在 Maze 中 并 让 每 一 个 Maze 创 建 它 自 身 。
但 将 Maze 变 得 小 一 些 使 得 它 能 更 容 易 被 理 解 和 修 改 , 而 且 standardMazeBuiIder 易 于 从 Maze 中
分 离 。 更 重 要 的 是 , 将 两 者 分 离 使 得 你 可 以 有 多 种 MazeB 回 der , 每 一 种 使 用 不 同 的 房 间 、 墙
壁 和 门 的 类 。

对比

抽象工厂模式强调的是创造不同系列的产品,所以每个产品都有一个抽象类,比如window。而builder模式中,可能无法抽取公共产品抽象类,它更强调产品的构建方式,所以void StandardMazeBuilder :: BuildRoom (int n) 中直接定义了房间是怎么构建的,而在抽象工厂模式这个过程不在MazeFactory 里面而在Maze *MazeGame:: CreateMaze(MazeFactory & factory)函数里,也就是说MazeFactory 只负责创建不同类型的产品,客户负责组装;Builder 则自己组装想要的产品,客户直接拿

你可能感兴趣的:(设计模式,设计模式)