【设计模式】创建型模式02:工厂模式

工厂模式


OVERVIOW

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

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

1.简单工厂

#mermaid-svg-S0CTyimT1XAZTpOp{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-S0CTyimT1XAZTpOp .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-S0CTyimT1XAZTpOp .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-S0CTyimT1XAZTpOp .error-icon{fill:#552222;}#mermaid-svg-S0CTyimT1XAZTpOp .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-S0CTyimT1XAZTpOp .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-S0CTyimT1XAZTpOp .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-S0CTyimT1XAZTpOp .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-S0CTyimT1XAZTpOp .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-S0CTyimT1XAZTpOp .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-S0CTyimT1XAZTpOp .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-S0CTyimT1XAZTpOp .marker{fill:#333333;stroke:#333333;}#mermaid-svg-S0CTyimT1XAZTpOp .marker.cross{stroke:#333333;}#mermaid-svg-S0CTyimT1XAZTpOp svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-S0CTyimT1XAZTpOp p{margin:0;}#mermaid-svg-S0CTyimT1XAZTpOp g.classGroup text{fill:#9370DB;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-S0CTyimT1XAZTpOp g.classGroup text .title{font-weight:bolder;}#mermaid-svg-S0CTyimT1XAZTpOp .cluster-label text{fill:#333;}#mermaid-svg-S0CTyimT1XAZTpOp .cluster-label span{color:#333;}#mermaid-svg-S0CTyimT1XAZTpOp .cluster-label span p{background-color:transparent;}#mermaid-svg-S0CTyimT1XAZTpOp .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-S0CTyimT1XAZTpOp .cluster text{fill:#333;}#mermaid-svg-S0CTyimT1XAZTpOp .cluster span{color:#333;}#mermaid-svg-S0CTyimT1XAZTpOp .nodeLabel,#mermaid-svg-S0CTyimT1XAZTpOp .edgeLabel{color:#131300;}#mermaid-svg-S0CTyimT1XAZTpOp .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-S0CTyimT1XAZTpOp .label text{fill:#131300;}#mermaid-svg-S0CTyimT1XAZTpOp .labelBkg{background:#ECECFF;}#mermaid-svg-S0CTyimT1XAZTpOp .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-S0CTyimT1XAZTpOp .classTitle{font-weight:bolder;}#mermaid-svg-S0CTyimT1XAZTpOp .node rect,#mermaid-svg-S0CTyimT1XAZTpOp .node circle,#mermaid-svg-S0CTyimT1XAZTpOp .node ellipse,#mermaid-svg-S0CTyimT1XAZTpOp .node polygon,#mermaid-svg-S0CTyimT1XAZTpOp .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-S0CTyimT1XAZTpOp .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-S0CTyimT1XAZTpOp g.clickable{cursor:pointer;}#mermaid-svg-S0CTyimT1XAZTpOp g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-S0CTyimT1XAZTpOp g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-S0CTyimT1XAZTpOp .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-S0CTyimT1XAZTpOp .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-S0CTyimT1XAZTpOp .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-S0CTyimT1XAZTpOp .dashed-line{stroke-dasharray:3;}#mermaid-svg-S0CTyimT1XAZTpOp .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-S0CTyimT1XAZTpOp #compositionStart,#mermaid-svg-S0CTyimT1XAZTpOp .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-S0CTyimT1XAZTpOp #compositionEnd,#mermaid-svg-S0CTyimT1XAZTpOp .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-S0CTyimT1XAZTpOp #dependencyStart,#mermaid-svg-S0CTyimT1XAZTpOp .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-S0CTyimT1XAZTpOp #dependencyStart,#mermaid-svg-S0CTyimT1XAZTpOp .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-S0CTyimT1XAZTpOp #extensionStart,#mermaid-svg-S0CTyimT1XAZTpOp .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-S0CTyimT1XAZTpOp #extensionEnd,#mermaid-svg-S0CTyimT1XAZTpOp .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-S0CTyimT1XAZTpOp #aggregationStart,#mermaid-svg-S0CTyimT1XAZTpOp .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-S0CTyimT1XAZTpOp #aggregationEnd,#mermaid-svg-S0CTyimT1XAZTpOp .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-S0CTyimT1XAZTpOp #lollipopStart,#mermaid-svg-S0CTyimT1XAZTpOp .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-S0CTyimT1XAZTpOp #lollipopEnd,#mermaid-svg-S0CTyimT1XAZTpOp .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-S0CTyimT1XAZTpOp .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-S0CTyimT1XAZTpOp .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-S0CTyimT1XAZTpOp .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-S0CTyimT1XAZTpOp .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-S0CTyimT1XAZTpOp :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 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
  • 适用场景:产品种类少,且很少新增产品时。
cpp 复制代码
// 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; }
};
cpp 复制代码
// 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;
  }
};
cpp 复制代码
// 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.工厂模式/工厂方法

#mermaid-svg-PdJ2C4kTM9JwGjcL{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-PdJ2C4kTM9JwGjcL .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-PdJ2C4kTM9JwGjcL .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-PdJ2C4kTM9JwGjcL .error-icon{fill:#552222;}#mermaid-svg-PdJ2C4kTM9JwGjcL .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-PdJ2C4kTM9JwGjcL .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-PdJ2C4kTM9JwGjcL .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-PdJ2C4kTM9JwGjcL .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-PdJ2C4kTM9JwGjcL .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-PdJ2C4kTM9JwGjcL .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-PdJ2C4kTM9JwGjcL .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-PdJ2C4kTM9JwGjcL .marker{fill:#333333;stroke:#333333;}#mermaid-svg-PdJ2C4kTM9JwGjcL .marker.cross{stroke:#333333;}#mermaid-svg-PdJ2C4kTM9JwGjcL svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-PdJ2C4kTM9JwGjcL p{margin:0;}#mermaid-svg-PdJ2C4kTM9JwGjcL g.classGroup text{fill:#9370DB;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-PdJ2C4kTM9JwGjcL g.classGroup text .title{font-weight:bolder;}#mermaid-svg-PdJ2C4kTM9JwGjcL .cluster-label text{fill:#333;}#mermaid-svg-PdJ2C4kTM9JwGjcL .cluster-label span{color:#333;}#mermaid-svg-PdJ2C4kTM9JwGjcL .cluster-label span p{background-color:transparent;}#mermaid-svg-PdJ2C4kTM9JwGjcL .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-PdJ2C4kTM9JwGjcL .cluster text{fill:#333;}#mermaid-svg-PdJ2C4kTM9JwGjcL .cluster span{color:#333;}#mermaid-svg-PdJ2C4kTM9JwGjcL .nodeLabel,#mermaid-svg-PdJ2C4kTM9JwGjcL .edgeLabel{color:#131300;}#mermaid-svg-PdJ2C4kTM9JwGjcL .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-PdJ2C4kTM9JwGjcL .label text{fill:#131300;}#mermaid-svg-PdJ2C4kTM9JwGjcL .labelBkg{background:#ECECFF;}#mermaid-svg-PdJ2C4kTM9JwGjcL .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-PdJ2C4kTM9JwGjcL .classTitle{font-weight:bolder;}#mermaid-svg-PdJ2C4kTM9JwGjcL .node rect,#mermaid-svg-PdJ2C4kTM9JwGjcL .node circle,#mermaid-svg-PdJ2C4kTM9JwGjcL .node ellipse,#mermaid-svg-PdJ2C4kTM9JwGjcL .node polygon,#mermaid-svg-PdJ2C4kTM9JwGjcL .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-PdJ2C4kTM9JwGjcL .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-PdJ2C4kTM9JwGjcL g.clickable{cursor:pointer;}#mermaid-svg-PdJ2C4kTM9JwGjcL g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-PdJ2C4kTM9JwGjcL g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-PdJ2C4kTM9JwGjcL .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-PdJ2C4kTM9JwGjcL .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-PdJ2C4kTM9JwGjcL .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-PdJ2C4kTM9JwGjcL .dashed-line{stroke-dasharray:3;}#mermaid-svg-PdJ2C4kTM9JwGjcL .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-PdJ2C4kTM9JwGjcL #compositionStart,#mermaid-svg-PdJ2C4kTM9JwGjcL .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-PdJ2C4kTM9JwGjcL #compositionEnd,#mermaid-svg-PdJ2C4kTM9JwGjcL .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-PdJ2C4kTM9JwGjcL #dependencyStart,#mermaid-svg-PdJ2C4kTM9JwGjcL .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-PdJ2C4kTM9JwGjcL #dependencyStart,#mermaid-svg-PdJ2C4kTM9JwGjcL .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-PdJ2C4kTM9JwGjcL #extensionStart,#mermaid-svg-PdJ2C4kTM9JwGjcL .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-PdJ2C4kTM9JwGjcL #extensionEnd,#mermaid-svg-PdJ2C4kTM9JwGjcL .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-PdJ2C4kTM9JwGjcL #aggregationStart,#mermaid-svg-PdJ2C4kTM9JwGjcL .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-PdJ2C4kTM9JwGjcL #aggregationEnd,#mermaid-svg-PdJ2C4kTM9JwGjcL .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-PdJ2C4kTM9JwGjcL #lollipopStart,#mermaid-svg-PdJ2C4kTM9JwGjcL .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-PdJ2C4kTM9JwGjcL #lollipopEnd,#mermaid-svg-PdJ2C4kTM9JwGjcL .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-PdJ2C4kTM9JwGjcL .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-PdJ2C4kTM9JwGjcL .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-PdJ2C4kTM9JwGjcL .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-PdJ2C4kTM9JwGjcL .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-PdJ2C4kTM9JwGjcL :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 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

  • 核心:将工厂抽象化,定义创建产品的抽象方法,具体创建哪个产品由子类工厂决定(延迟实例化)。
  • 优点:符合开闭原则,新增产品时只需要新增一个产品类、以及对应的工厂子类,老代码无需修改。
  • 缺点:每新增一个产品,就需要增加产品类、工厂类,容易导致类爆炸。
  • 适用场景:产品种类多,且经常扩展新产品。
cpp 复制代码
// 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; }
};
cpp 复制代码
// 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; };
};
cpp 复制代码
// 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主题、或切换数据库连接池\日志\缓存的全家桶)

以造船为例子:

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

#mermaid-svg-Xt9BzlkIxXJom5Ez{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Xt9BzlkIxXJom5Ez .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Xt9BzlkIxXJom5Ez .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Xt9BzlkIxXJom5Ez .error-icon{fill:#552222;}#mermaid-svg-Xt9BzlkIxXJom5Ez .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Xt9BzlkIxXJom5Ez .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Xt9BzlkIxXJom5Ez .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Xt9BzlkIxXJom5Ez .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Xt9BzlkIxXJom5Ez .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Xt9BzlkIxXJom5Ez .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Xt9BzlkIxXJom5Ez .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Xt9BzlkIxXJom5Ez .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Xt9BzlkIxXJom5Ez .marker.cross{stroke:#333333;}#mermaid-svg-Xt9BzlkIxXJom5Ez svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Xt9BzlkIxXJom5Ez p{margin:0;}#mermaid-svg-Xt9BzlkIxXJom5Ez g.classGroup text{fill:#9370DB;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-Xt9BzlkIxXJom5Ez g.classGroup text .title{font-weight:bolder;}#mermaid-svg-Xt9BzlkIxXJom5Ez .cluster-label text{fill:#333;}#mermaid-svg-Xt9BzlkIxXJom5Ez .cluster-label span{color:#333;}#mermaid-svg-Xt9BzlkIxXJom5Ez .cluster-label span p{background-color:transparent;}#mermaid-svg-Xt9BzlkIxXJom5Ez .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Xt9BzlkIxXJom5Ez .cluster text{fill:#333;}#mermaid-svg-Xt9BzlkIxXJom5Ez .cluster span{color:#333;}#mermaid-svg-Xt9BzlkIxXJom5Ez .nodeLabel,#mermaid-svg-Xt9BzlkIxXJom5Ez .edgeLabel{color:#131300;}#mermaid-svg-Xt9BzlkIxXJom5Ez .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-Xt9BzlkIxXJom5Ez .label text{fill:#131300;}#mermaid-svg-Xt9BzlkIxXJom5Ez .labelBkg{background:#ECECFF;}#mermaid-svg-Xt9BzlkIxXJom5Ez .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-Xt9BzlkIxXJom5Ez .classTitle{font-weight:bolder;}#mermaid-svg-Xt9BzlkIxXJom5Ez .node rect,#mermaid-svg-Xt9BzlkIxXJom5Ez .node circle,#mermaid-svg-Xt9BzlkIxXJom5Ez .node ellipse,#mermaid-svg-Xt9BzlkIxXJom5Ez .node polygon,#mermaid-svg-Xt9BzlkIxXJom5Ez .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Xt9BzlkIxXJom5Ez .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-Xt9BzlkIxXJom5Ez g.clickable{cursor:pointer;}#mermaid-svg-Xt9BzlkIxXJom5Ez g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-Xt9BzlkIxXJom5Ez g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-Xt9BzlkIxXJom5Ez .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-Xt9BzlkIxXJom5Ez .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-Xt9BzlkIxXJom5Ez .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-Xt9BzlkIxXJom5Ez .dashed-line{stroke-dasharray:3;}#mermaid-svg-Xt9BzlkIxXJom5Ez .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-Xt9BzlkIxXJom5Ez #compositionStart,#mermaid-svg-Xt9BzlkIxXJom5Ez .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Xt9BzlkIxXJom5Ez #compositionEnd,#mermaid-svg-Xt9BzlkIxXJom5Ez .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Xt9BzlkIxXJom5Ez #dependencyStart,#mermaid-svg-Xt9BzlkIxXJom5Ez .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Xt9BzlkIxXJom5Ez #dependencyStart,#mermaid-svg-Xt9BzlkIxXJom5Ez .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Xt9BzlkIxXJom5Ez #extensionStart,#mermaid-svg-Xt9BzlkIxXJom5Ez .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Xt9BzlkIxXJom5Ez #extensionEnd,#mermaid-svg-Xt9BzlkIxXJom5Ez .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Xt9BzlkIxXJom5Ez #aggregationStart,#mermaid-svg-Xt9BzlkIxXJom5Ez .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Xt9BzlkIxXJom5Ez #aggregationEnd,#mermaid-svg-Xt9BzlkIxXJom5Ez .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Xt9BzlkIxXJom5Ez #lollipopStart,#mermaid-svg-Xt9BzlkIxXJom5Ez .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Xt9BzlkIxXJom5Ez #lollipopEnd,#mermaid-svg-Xt9BzlkIxXJom5Ez .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-Xt9BzlkIxXJom5Ez .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-Xt9BzlkIxXJom5Ez .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Xt9BzlkIxXJom5Ez .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Xt9BzlkIxXJom5Ez .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Xt9BzlkIxXJom5Ez :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 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

代码实现:

cpp 复制代码
// 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_;
};
cpp 复制代码
// 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; };
};
cpp 复制代码
// 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;
}
相关推荐
(Charon)17 小时前
【C++】锁与原子操作(四):自旋锁的完整实现与性能优化
c语言·开发语言·c++
ShineWinsu18 小时前
对于Linux:五种IO模型以及非阻塞IO的详细解析
linux·c++·面试·io·阻塞·非阻塞·fcntl
梅头脑19 小时前
学了6种设计模式却写出了同事看不懂的代码——SOLID五原则反例对照,治好了我的"过度设计"
设计模式
呜喵王阿尔萨斯19 小时前
extern “C“ in C++
c语言·c++·算法
乐观勇敢坚强的老彭19 小时前
C++信奥静态数组和动态数组
数据结构·c++·算法
gumichef20 小时前
第一章:面向对象核心——类和对象深度讲解
开发语言·c++
ao-weilai20 小时前
C++基础:类和对象
开发语言·c++
郝学胜-神的一滴20 小时前
[简化版 GAMES 104] 现代游戏引擎 04:从0到1构建你的游戏世界
c++·游戏·unity·游戏引擎·软件工程·unreal engine
Bryce学亮20 小时前
FileLine,基于 Qt 6 + QML 构建的跨平台文件传输与即时通讯工具
数据库·c++·人工智能·python·qt·github
旖旎夜光20 小时前
LeetCode 991: 坏了的计算器(贪心算法) —— 题解
数据结构·c++·算法·leetcode·贪心算法