工厂模式


工厂模式通常指的就是工厂方法模式 Factory Method,区别于简单工厂与抽象工厂模式。

  1. 简单工厂:创建对象交给一个工厂类,根据参数返回不同产品。缺点:增加新产品需要修改工厂类,违反开闭原则(OCP)
  2. 工厂模式/工厂方法:定义创建对象的抽象方法,由子类决定实例化哪个具体的类,符合开闭原则。
  3. 抽象工厂:强调产品族,当有多个产品等级结构时使用。

1.简单工厂

creates

creates

creates

SheepProduct

+transform()

+ability()

LionProduct

+transform()

+ability()

BatProduct

+transform()

+ability()

Factory

+createProduct(ProductType) : AbstractProduct

«abstract»

AbstractProduct

+transform()

+ability()

简单工厂并不是GoF设计模式圣经中的23中经典模式,而工厂模式/工厂方法,和抽象工厂才是正式的经典模式:

  • 核心:创建工厂类,根据传入参数用 if-elseswitch case 来决定返回哪个具体产品。
  • 优点:调用方不用关心对象如new,解耦了创建和使用。
  • 缺点:违背开闭原则,如果要新增加产品,必须修改工厂类的内部逻辑,增加 if-else
  • 适用场景:产品种类少,且很少新增产品时。
// product.h
enum class ProductType : char {
  Sheep,
  Lion,
  Bat,
};
class AbstractProduct {
 public:
  virtual void transform() = 0;
  virtual void ability() = 0;
  virtual ~AbstractProduct() {};
};
class SheepProduct : public AbstractProduct {
 public:
  void transform() override { std::cout << "transform to sheep." << std::endl; }
  void ability() override { std::cout << "arms are turned into goat horns." << std::endl; }
};
class LionProduct : public AbstractProduct {
 public:
  void transform() override { std::cout << "transform to alion." << std::endl; }
  void ability() override { std::cout << "breathe fire." << std::endl; }
};
class BatProduct : public AbstractProduct {
 public:
  void transform() override { std::cout << "transform to bat." << std::endl; }
  void ability() override { std::cout << "unleash the Myriad Swords." << std::endl; }
};
// factory.h
class Factory {
 public:
  AbstractProduct* createPorduct(ProductType type) {
    AbstractProduct* product = nullptr;
    switch (type) {
      case ProductType::Sheep: {
        product = new SheepProduct;
        break;
      }
      case ProductType::Lion: {
        product = new LionProduct;
        break;
      }
      case ProductType::Bat: {
        product = new BatProduct;
        break;
      }
      default:
        break;
    }
    return product;
  }
};
// test.hpp
void test_simple_factory() {
  auto factory = std::make_unique<Factory>();
  std::unique_ptr<AbstractProduct> product(factory->createPorduct(ProductType::Lion));
  if (!product) {
    std::cout << "factory createPorduct failed..." << std::endl;
    return;
  }
  product->transform();
  product->ability();
}

2.工厂模式/工厂方法

creates

creates

creates

«abstract»

AbstractProduct

+transform()

+ability()

SheepProduct

+transform()

+ability()

LionProduct

+transform()

+ability()

BatProduct

+transform()

+ability()

«abstract»

AbstractFactory

+createProduct() : AbstractProduct

SheepFactory

+createProduct() : AbstractProduct

LionFactory

+createProduct() : AbstractProduct

BatFactory

+createProduct() : AbstractProduct

  • 核心:将工厂抽象化,定义创建产品的抽象方法,具体创建哪个产品由子类工厂决定(延迟实例化)。
  • 优点:符合开闭原则,新增产品时只需要新增一个产品类、以及对应的工厂子类,老代码无需修改。
  • 缺点:每新增一个产品,就需要增加产品类、工厂类,容易导致类爆炸。
  • 适用场景:产品种类多,且经常扩展新产品。
// product.h
class AbstractProduct {
 public:
  virtual void transform() = 0;
  virtual void ability() = 0;
  virtual ~AbstractProduct() {};
};
class SheepProduct : public AbstractProduct {
 public:
  void transform() override { std::cout << "transform to sheep." << std::endl; }
  void ability() override { std::cout << "arms are turned into goat horns." << std::endl; }
};
class LionProduct : public AbstractProduct {
 public:
  void transform() override { std::cout << "transform to alion." << std::endl; }
  void ability() override { std::cout << "breathe fire." << std::endl; }
};
class BatProduct : public AbstractProduct {
 public:
  void transform() override { std::cout << "transform to bat." << std::endl; }
  void ability() override { std::cout << "unleash the Myriad Swords." << std::endl; }
};
// factory.h
class AbstractFactory {
 public:
  virtual AbstractProduct* createPorduct() = 0;
  virtual ~AbstractFactory() {};
};
class SheepFactory : public AbstractFactory {
 public:
  AbstractProduct* createPorduct() override { return new SheepProduct; }
  virtual ~SheepFactory() { std::cout << "SheepFactory destructor called." << std::endl; };
};
class LionFactory : public AbstractFactory {
 public:
  AbstractProduct* createPorduct() override { return new LionProduct; }
  virtual ~LionFactory() { std::cout << "LionFactory destructor called." << std::endl; };
};
class BatFactory : public AbstractFactory {
 public:
  AbstractProduct* createPorduct() override { return new BatProduct; }
  virtual ~BatFactory() { std::cout << "BatFactory destructor called." << std::endl; };
};
// test.hpp
void test_factory_method() {
  auto factory = std::make_unique<BatFactory>();
  std::unique_ptr<AbstractProduct> product(factory->createPorduct());
  if (!product) {
    std::cout << "factory createPorduct failed..." << std::endl;
    return;
  }
  product->transform();
  product->ability();
}

3.抽象工厂

  • 核心:不生产单一产品,而是生产整套产品(产品族)。
  • 优点:保证配套产品的一致性(华为工厂生产的手机、路由器、耳机全都是同个华为工厂生产的)
  • 缺点:新增产品种类较难,如果在工厂中增加 createWatch() 方法,所有品牌子类工厂都得修改。
  • 适用场景:系统需要更换整套外观\风格\品牌(如换一套UI主题、或切换数据库连接池\日志\缓存的全家桶)

以造船为例子:

基础版标准版旗舰版
外观木头钢铁合成金属
动力手动内燃机核动力
武器速射炮激光

creates

creates

creates

creates

creates

creates

creates

creates

creates

WoodAppearance

+display()

SteelAppearance

+display()

SyntheticAppearance

+display()

ManualEngine

+run()

CombustionEngine

+run()

NuclearEngine

+run()

Gun

+fire()

RapidFireGun

+fire()

Laser

+fire()

«abstract»

AbstractAppearance

+display()

«abstract»

AbstractEngine

+run()

«abstract»

AbstractWeapon

+fire()

«abstract»

AbstractShipFactory

+createAppearance() : AbstractAppearance

+createEngine() : AbstractEngine

+createWeapon() : AbstractWeapon

BasicShipFactory

+createAppearance() : AbstractAppearance

+createEngine() : AbstractEngine

+createWeapon() : AbstractWeapon

StandardShipFactory

+createAppearance() : AbstractAppearance

+createEngine() : AbstractEngine

+createWeapon() : AbstractWeapon

FlagshipShipFactory

+createAppearance() : AbstractAppearance

+createEngine() : AbstractEngine

+createWeapon() : AbstractWeapon

代码实现:

// product.h
// appearance
class ShipApprearance {
 public:
  virtual const std::string getAppearance() = 0;
  virtual ~ShipApprearance() {};
};
class ShipWoodAppearance : public ShipApprearance {
 public:
  const std::string getAppearance() override { return "wood appearance."; }
};
class ShipMetalAppearance : public ShipApprearance {
 public:
  const std::string getAppearance() override { return "metal appearance."; }
};
class ShipSyntheticAppearance : public ShipApprearance {
 public:
  const std::string getAppearance() override { return "synthetic appearance."; }
};
// engine
class ShipEngine {
 public:
  virtual const std::string getEngine() = 0;
  virtual ~ShipEngine() {};
};
class ShipManualEngine : public ShipEngine {
 public:
  const std::string getEngine() override { return "manual engine."; }
};
class ShipSteamEngine : public ShipEngine {
 public:
  const std::string getEngine() override { return "steam engine."; }
};
class ShipNuclearEngine : public ShipEngine {
 public:
  const std::string getEngine() override { return "nuclear engine."; }
};
// weapon
class ShipWeapon {
 public:
  virtual const std::string getWeapon() = 0;
  virtual ~ShipWeapon() {};
};
class ShipGunWeapon : public ShipWeapon {
 public:
  const std::string getWeapon() override { return "gun weapon."; }
};
class ShipCannonWeapon : public ShipWeapon {
 public:
  const std::string getWeapon() override { return "cannon weapon."; }
};
class ShipLaserWeapon : public ShipWeapon {
 public:
  const std::string getWeapon() override { return "laser weapon."; }
};
// ship
class Ship {
 public:
  Ship(ShipApprearance* appr, ShipEngine* engine, ShipWeapon* weapon)
    : appearance_(appr), engine_(engine), weapon_(weapon) {};
  ~Ship() {};
  const std::string getProperty() {
    return "Ship appearance:" + appearance_->getAppearance() + " engine:" + engine_->getEngine() +
           " weapon:" + weapon_->getWeapon();
  }

 private:
  std::unique_ptr<ShipApprearance> appearance_;
  std::unique_ptr<ShipEngine> engine_;
  std::unique_ptr<ShipWeapon> weapon_;
};
// factory.h
class AbstractShipFactory {
 public:
  virtual Ship* createShip() = 0;
  virtual ~AbstractShipFactory() {};
};
class BasicShipFactory : public AbstractShipFactory {
 public:
  Ship* createShip() override {
    ShipApprearance* appr = new ShipWoodAppearance;
    ShipEngine* engine = new ShipManualEngine;
    ShipWeapon* weapon = new ShipGunWeapon;
    return new Ship(appr, engine, weapon);
  }
  virtual ~BasicShipFactory() { std::cout << "BasicShipFactory destructor called." << std::endl; };
};
class StandardShipFactory : public AbstractShipFactory {
 public:
  Ship* createShip() override {
    ShipApprearance* appr = new ShipSyntheticAppearance;
    ShipEngine* engine = new ShipSteamEngine;
    ShipWeapon* weapon = new ShipCannonWeapon;
    return new Ship(appr, engine, weapon);
  }
  virtual ~StandardShipFactory() { std::cout << "StandardShipFactory destructor called." << std::endl; };
};
class AdvancedShipFactory : public AbstractShipFactory {
 public:
  Ship* createShip() override {
    ShipApprearance* appr = new ShipMetalAppearance;
    ShipEngine* engine = new ShipNuclearEngine;
    ShipWeapon* weapon = new ShipLaserWeapon;
    return new Ship(appr, engine, weapon);
  }
  virtual ~AdvancedShipFactory() { std::cout << "AdvancedShipFactory destructor called." << std::endl; };
};
// test.hpp
void test_factory_abstract() {
  using namespace factory_abstract;
  std::unique_ptr<AbstractShipFactory> factory;
  std::unique_ptr<Ship> ship;
  // basic ship
  factory = std::make_unique<BasicShipFactory>();
  ship.reset(factory->createShip());
  if (!ship) {
    std::cout << "factory createShip failed..." << std::endl;
    return;
  }
  std::cout << ship->getProperty() << std::endl;
  // standard ship
  factory = std::make_unique<StandardShipFactory>();
  ship.reset(factory->createShip());
  if (!ship) {
    std::cout << "factory createShip failed..." << std::endl;
    return;
  }
  std::cout << ship->getProperty() << std::endl;
  // advanced ship
  factory = std::make_unique<AdvancedShipFactory>();
  ship.reset(factory->createShip());
  if (!ship) {
    std::cout << "factory createShip failed..." << std::endl;
    return;
  }
  std::cout << ship->getProperty() << std::endl;
}

更多推荐