抽象工厂模式

抽象工厂模式

回顾其他两个工厂模式

简易工厂将所有逻辑都封装在一个工厂类中, 工厂依据客户提供的名字创建对应的产品

工厂方法将产品创建过程封装到一个具体的工厂类中, 每一个工厂可以创建一个具体的产品, 所以需要创建很多工厂

介绍

一个工厂不止可以建造一个产品, 他可以建造多个. 比如一个关于运动工厂, 他可以建造篮球, 足球 …

总之,一个工厂可以提供创建多种相关产品的接口,而无需像工厂方法一样,为每一个产品都提供一个具体工厂。

定义

抽象工厂模式结构与工厂方法模式结构类似,不同之处在于,一个具体工厂可以生产多种同类相关的产品:

抽象工厂(AbstractFactory):所有生产具体产品的工厂类的基类,提供工厂类的公共方法;
具体工厂(ConcreteFactory):生产具体的产品
抽象产品(AbstractProduct):所有产品的基类,提供产品类的公共方法
具体产品(ConcreteProduct):具体的产品类

流程

• 抽象产品类AbstractBall, 球类的基类,定义抽象方法play

class AbstractBall {
 public:
  virtual ~AbstractBall() = default;
  virtual void play() = 0;
};

• 具体产品类, 分别为Basketball、Football、Volleyball,具体实现方法play

class BasketBall : public AbstractBall {
 public:
  BasketBall() { play(); }
  void play() override { std::cout << "play basketball" << std::endl; }
};

class Football : public AbstractBall {
 public:
  Football() { play(); }
  void play() override { std::cout << "play football" << std::endl; }
};

class Volleyball : public AbstractBall {
 public:
  Volleyball() { play(); }
  void play() override { std::cout << "play volleyball" << std::endl; }
};

• 抽象产品类AbstractShirt:球衣类的基类,定义抽象方法wear

class AbstractShirt {
 public:
  virtual ~AbstractShirt() = default;
  virtual void wear() = 0;
};

具体产品类BasketballShirt、FootballShirt、VolleyballShirt,具体实现方法wear

class BasketShirt : public AbstractShirt {
 public:
  BasketShirt() { wear();}
  void wear() override { std::cout << "wear basketShirt" << std::endl;}
};

class FootballShirt : public AbstractShirt {
 public:
  FootballShirt() { wear();}
  void wear() override { std::cout << "wear footballShirt" << std::endl;}
};

class VolleyballShirt : public AbstractShirt {
 public:
  VolleyballShirt() { wear();}
  void wear() override { std::cout << "wear volleyballShirt" << std::endl;}
};

• 定义抽象工厂AbstractFactory,声明两个方法createBall 和 createShirt

class AbstractFactory {
 public:
  virtual ~AbstractFactory() = default;
  virtual std::shared_ptr<AbstractBall> createBall() = 0;
  virtual std::shared_ptr<AbstractShirt> createShirt() = 0;
};

• 定义具体工厂,重新具体实现两个方法

class BasketballFactory : public AbstractFactory {
 public:
  std::shared_ptr<AbstractBall> createBall() override { return std::make_shared<BasketBall>(); }
  std::shared_ptr<AbstractShirt> createShirt() override { return std::make_shared<BasketShirt>();}
};

class FootballFactory : public AbstractFactory {
 public:
  std::shared_ptr<AbstractBall> createBall() override { return std::make_shared<Football>(); }
  std::shared_ptr<AbstractShirt> createShirt() override { return std::make_shared<FootballShirt>();}
};

class VolleyballFactory : public AbstractFactory {
 public:
  std::shared_ptr<AbstractBall> createBall() override { return std::make_shared<Volleyball>(); }
  std::shared_ptr<AbstractShirt> createShirt() override { return std::make_shared<VolleyballShirt>();}
};

• 客户使用方式

int main() {
  std::shared_ptr<AbstractFactory> factory = nullptr;
  factory = std::make_shared<BasketballFactory>();
  factory->createBall();
  factory->createShirt();
  factory = std::make_shared<FootballFactory>();
  factory->createBall();
  factory->createShirt();
  factory = std::make_shared<VolleyballFactory>();
  factory->createBall();
  factory->createShirt();
  return 0;
}

效果

./bin/design/AbstractFactory
play basketball
wear basketShirt
play football
wear footballShirt
play volleyball
wear volleyballShirt

总结

抽象工厂在增加一个系列的产品时 只需要增加一个对应产品的工厂就ok了.

但是在已有的具体产品中如果需要新增一类产品, 比如需要一个袜子, 鞋子就需要增加对应的接口和修改对应的工厂类.

优点:

  • 工厂方法用于创建客户所需产品,同时向客户隐藏某个具体产品类将被实例化的细节,用户只需关心所需产品对应的工厂;
  • 新加入产品系列时,无需修改原有系统,增强了系统的可扩展性,符合开闭原则。

缺点:

  • 在已有产品系列中添加新产品时需要修改抽象层代码,对原有系统改动较大,违背开闭原则

适用

  • 一系列/一族产品需要被同时使用时,适合使用抽象工厂模式;
  • 产品结构稳定,设计完成之后不会向系统中新增或剔除某个产品

三种工厂模式中,简单工厂和工厂方法比较常用,抽象工厂的应用场景比较特殊,所以很少用到.

工厂模式,它的作用无外乎下面这四个。这也是判断要不要使用工厂模式的最本质的参考标准。

  • 封装变化:创建逻辑有可能变化,封装成工厂类之后,创建逻辑的变更对调用者透明。
  • 代码复用:创建代码抽离到独立的工厂类之后可以复用。
  • 隔离复杂性:封装复杂的创建逻辑,调用者无需了解如何创建对象。
  • 控制复杂度:将创建代码抽离出来,让原本的函数或类职责更单一,代码更简洁。

代码

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值