码迷,mamicode.com
首页 > 其他好文 > 详细

面向对象设计——抽象工厂(Abstract Factory)模式

时间:2017-08-02 18:59:13      阅读:221      评论:0      收藏:0      [点我收藏+]

标签:mbed   bst   迷宫   设计模式   技术分享   cte   public   virtual   声明   

定义

  提供一个创建一系列相关或者相互依赖对象的接口,而无需指定它们具体的类。抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要知道或关心实际产出的具体产品是什么。这样一来,客户就能从具体的产品中被解耦。

适用场景

  在以下情况可以使用Abstract Factory模式

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

UML图

技术分享

                  抽象工厂模式UML图a)

  • AbstractFactory  

  ——声明一个创建抽象产品对象的操作接口。

  • ConcreteFactory

  ——实现创建具体产品对象的操作。

  • AbstractProduct

  ——为一类产品对象声明一个接口。

  • ConcreteProduct

  ——定义一个将被相应的具体工厂创建的产品对象。

  ——实现AbstractProduct接口。

  在这里指的是ProductA1,ProductA2,ProductB1,ProductB2。

  • Client

  ——仅适用由AbstractFactory和AbstractProduct类声明的接口。

  一般而言,有多少个产品等级结构,就会在工厂角色中发现多少个工厂方法。每一个产品等级结构中有多少个具体的产品,就有多少个产品族,也就会在工厂等级结构中发现多少个具体工厂。

代码示例

   《设计模式:可复用面向对象软件的基础》中一书中,给出了一个应用工厂方法设计迷宫的例子,这里修改为应用抽象工厂模式来实现。

  首先,给出了枚举类型Direction表明东南西北四个方向,定义抽象产品AbstractProduct接口,包含一个纯虚函数Enter,用于在迷宫间移动位置。

enum Direction {North, South, East, West};

//AbstractProduct
class MapSite{
public:
    virtual void Enter() = 0;
};

   接下来,基于抽象产品接口MapSite实现ConcreteProduct具体产品类:

  定义迷宫房间Room类(ProductA);

//ProductA
class Room : public MapSite{
public:
    Room(int roomNo);//初始化房间号

    MapSite *GetSide(Direction) const;//获取当前房间四周具体产品ConcreteProduct类MapSite
    void SetSide(Direction, MapSite*);//设置当前房间四周具体产品ConcreteProduct类MapSite
   virtual void Enter(); 
private:
   MapSite
* _side[4];
   int _roomNumber;
};

   定义迷宫的墙Wall类(ProductB);

//ProductB
class Wall : public MapSite{
public:
    Wall();

    virtual void Enter();
};

    定义迷宫的门Door类(ProductC);

//ProductC
class Door : public MapSite{
public:
    Door(Room * = 0, Room * = 0);//初始化门两边的房间

    virtual void Enter();
    Room* OtherSideFrom(Room *);
private:
    Room * _room1;
    Room * _room2;
    bool _isOpen;
};

   定义迷宫Maze类(ProductD); 

//ProductD
class Maze{
public:
    Maze();

    void AddRoom(Room *);
    Room* RoomNo(int) const;
private:
    //...
};

   在完成抽象产品接口和具体产品类定义后,接下来定义抽象工厂接口AbstractFactory类MazeFactory,对外提供接口,用于生成上述定义的具体产品类ProductA——Room,ProductB——Wall,ProductC——Door,ProductD——Maze。

//AbstractFactory
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(r1,r2);}
};

   在定义好抽象工厂接口、抽象产品接口、具体产品后,就可以由Client来动态创建和处理各个对象的关系,这里创建一个包含两个房间的简单迷宫。

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

   如果需要创建带各种特效或者属性的Room、Door、Wall ,只需要继承具体产品类ProductA、ProductB、ProductC、ProductD,以及抽象工厂AbstractFactory接口MazeFactory。

  如果要生成魔法迷宫,只需要继承MazeFactory生成ConcreteFactory类EnchantedMazeFacotry,

//ConcreteFactory
class EnchantedMazeFactory:public MazeFactory{
public:
    EnchantedMazeFacotry();

    virtual Room* MakeRoom(int n) const
    {return new EnchantedRoom(n, castSpell());}
    virtual Door* MakeDoor(Room* r1, Room* r2) const
    {return new DoorNeedingSpell(r1,r2);}
protected:
    Spell* CastSpell() const;
};

   调用CreateMaze就可以生成带魔法房间和符咒门的迷宫了。。。

//Client
MazeFactory
*enchantedMazeFac = new EnchantedMazeFactory ;
Maze
*enchantedMaze = CreateMaze(enchantedMazeFac);

   同理还可以,由爆炸工厂生成带爆炸门和爆炸房间的迷宫。。。

Wall * BombedMazeFactory::MakeWall() const {
    return new BombedWall;
}
Room* BombedMazeFactory::MakeRoom(int n) const{
    return new RoomWithABomb(n);
}

  如果嫌上面例子麻烦, 下面这个例子(截图自wikipedia官网),简单明了的阐释了抽象工厂模式:

技术分享

  

优缺点

优点:

1、抽象工厂模式隔离了具体类的生产,使得客户并不需要知道什么被创建。

2、当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。

3、增加新的具体工厂和产品族很方便,无须修改已有系统,符合“开闭原则”。

 

缺点:

增加新的产品等级结构很复杂,需要修改抽象工厂和所有的具体工厂类,对“开闭原则”的支持呈现倾斜性。

 

 

参考资料:

a) https://en.wikipedia.org/wiki/Abstract_factory_pattern

b) 《设计模式:可复用面向对象软件的基础》

c) http://www.runoob.com/design-pattern/abstract-factory-pattern.html

d) https://zh.wikipedia.org/wiki/%E6%8A%BD%E8%B1%A1%E5%B7%A5%E5%8E%82

面向对象设计——抽象工厂(Abstract Factory)模式

标签:mbed   bst   迷宫   设计模式   技术分享   cte   public   virtual   声明   

原文地址:http://www.cnblogs.com/chenyangchun/p/7183795.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!