设计模式学习笔记(抽象工厂模式)

来源:互联网 发布:java 工具类打包jar包 编辑:程序博客网 时间:2024/06/01 15:54

一、抽象工厂作用

1、概念:

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

抽象工厂模式的关键就是将这一组对象的创建封装到一个用于创建对象的类中。

2、辨析:

Abstract Factory模式和Factory最大的差别就是抽象工厂创建的是一系列相关的对象,其中创建的实现其实采用的就是Factory模式的方法,对于某个实现的有一个派生出来的工厂,另一个实现有另一个派生出来的工厂

工厂方法采用的是类继承机制(生成一个子类,重写该工厂方法,在该方法中生产一个对象);而抽象工厂采用的是对象组合机制,专门定义“工厂”对象来负责对象的创建。对象组合的方式就是把“工厂”对象作为参数传递。

3、抽象工厂模式的参与者有:

  1)AbstractFactory:抽象工厂。抽象工厂定义了一个接口,所有的具体工厂都通过该接口来生产产品。

  2)ConcreteFactory:具体工厂。具体工厂是用于生产不同产品族。要创建一个产品,客户只需要使用其中一个工厂完全不需要实例化任何产品对象。

  3)AbstractProduct:抽象产品。这是一个产品家族,每一个具体工厂都能够生产一整组产品。

  4)Product:具体产品。

  5)Client:只能看到抽象层次接口。

二、 抽象工厂应用场景

1、一个系统要独立于它的产品的创建、组合和表示时。
2、一个系统要由多个产品系列中的一个来配置时。
3、当你要强调一系列相关的产品对象的设计以便进行联合使用时。
4、当你提供一个产品类库,而只想显示它们的接口而不是实现时。

三、缺点

新增产品复杂。抽象工厂增加产品组件时,需要更改所有工厂的接口。如增加产品ProductC,则抽象工厂类和所有的具体工厂类都需要增加接口CreateProductC。

四、抽象工厂模式与工厂方法模式的区别

a.重点不同。工厂方法模式强调的是不同的创建者根据自身需求去生产不同的具体产品,重点是生产具体产品;而抽象工厂模式则定位为“在不指定实体类别的前提下,提供了一个可以创建一系列相关或互相依赖之组件的接口”,重点是创建相关组件。

b.抽象工厂提供了的“相关组件”可以看成是具体的产品(如ProductA1),抽象工厂模式的“相关组件”可由工厂模式实现。ConcreteFactory1.CreateProuductA()生产的具体产品,可以用工厂方法模式实现,即每一个产品用一个工厂方法实现。

c.工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。

d.抽象工厂不能直接创建产品,只能创建工厂,即抽象工厂创建的产品是工厂。虽然它也定义了创建产品的方法,但需要创建出来的具体的工厂实现,即抽象工厂创建出的工厂创建产品。

e.工厂方法采用的是类继承机制(生成一个子类,重写该工厂方法,在该方法中生产一个对象);而抽象工厂采用的是对象组合机制,专门定义“工厂”对象来负责对象的创建。对象组合的方式就是把“工厂”对象作为参数传递。

五、例子

图示:


代码:

class MazeFactory{//抽象工厂public:         MazeFactory();         virtual Maze* MakeMaze() const//产品对象1                    { return new Maze;}         virtual Wall*  MakeWall() const//产品对象2(相关组件的实现采用工厂模式)                    { return new Wall;}         virtual Room*  MakeRoom() const//产品对象3                    { return new Room(n);}         virtual Door*  MakeDoor(Room* r1,Room* r2) const//产品对象4                    { return new Door(r1,r2);}};


class EnchantedMazeFactory:public MazeFactory{//具体工厂public:         EnchantedMazeFactory();         virtual Room* MakeRoom(int n)  const{                   return new EnchantedRoom(n,CastSpell());}         virtual Door* MakeDoor(Room* r1,Room* r2)  const{                   return new DoorNeedSpell(r1,r2);}protected:         Spell* CastSpell() const;        }

Maze* MazeGame::CreateMaze(MazeFactory& factory){//抽象接口          Maze* aMaze = factory.MakeMaze();          Room* r1 = factory.MakeRoom(1);          Room* r2 = factory.MakeRoom(2);          Door* aDoor=factory.MackDoor(r1,r2);          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());          r1->SetSide(North,factory.MakeWall());          r2->SetSide(North,factory.MakeWall());          r2->SetSide(East,factory.MakeWall());          r2->SetSide(South,factory.MakeWall());          r2->SetSide(West,factory.MakeWall());          return aMaze;}