工厂模式

经常听人说工厂方法+反射机制+单例模式,可以解决大多数的对象创建的问题。但是什么是工厂方法呢?还有其他什么鬼呢?
这里先介绍简单的工厂方法,也就是Factory Method方法,既然这是简单的,那岂不是还有复制的或者其它,那是当然的。不过都得一步一步来嘛。

做什么?

首先明确我们用工厂模式做什么?
那么我们的客户来需求了,”我们要创建在一个模块中创建A类的对象“,
”没关系,我知道那个代码在哪里,我们就在那里创建A的对象。

// file1
class A {
 // ....
};  // class A
 
// ...
  A* a = new A();
 // ...

现在突然客户背后站了会说,“这个不太好,我们可能后面需要创建Class B, C , D ...”。
默默的说一句,md,你怎么这么多问题啊(小声)。 “没问题,我们改代码,那么我们将对象指针抽象一下,提一个基类吧,抽象一下,好吧。”

// commom file 
{
class Base {
  // ....
};  // class Base

}

// file1
{
class A : public Base{
 // ....
};  // class A
}

// file2 
{
class B : public Base{
 // ....
};  // class B
}
// ...
  Base* base = new A(); // Base* base = new B();
 // ...

这时候客户说,”好像哈,我觉得..., 是这样的,我觉得 你左边那部分好像有点那个意思了,但是你这右边还是有点不行啊,你用new创建,那不是和具体的创建绑定死了,
这不行你还得改。对了,五点我该下班了,你也早点下班“。
"md(低声), ok,没得问题"。

那么怎么办呢,感觉可能拨了键盘上的头发,这样吧,我们通过其他的类来返回这个对象指针吧。
既然是其他类返回的这个对象指针,那么我们就叫那个类为工厂类吧。

class BaseFactory {
public:
  Base* CreateNewBase {
    return new A(); // return new B();
  }
}

"完蛋,明天又要开例会了", 自己心中暗中一想,完蛋虽然上面这样写,好像是没有用new创建,但是不是还是换汤不换药嘛,还得改。
”咦,不是还有多态嘛“,对啊多态,这时候virtual一下子跳入了脑海。

class BaseFactory {
public:
  virtual Base* CreateNewBase = 0;
}

class FactoryA : public BaseFactory {
public:
  virtual Base* CreateNewBase override;
}

class FactoryB : public BaseFactory {
public:
  virtual Base* CreateNewBase override;
}

例会上,屁颠屁颠的和客户讲了下这个,感觉很自豪。
客户摸了摸自己浓密的头发,说到”不错,我就是想让你做成类似这个样,但是我当时没想起名字, 不错了,但是这里有个问题 。。。“
”啥,还有问题“。
”就是哈,我能不能通过注册的方式,申请一个类的对象啊,比如我只会配置json文件,我也看不懂代码, 而且我想通过一张表来保存我想创建的对象,随时随地创建可以吗“。
”。。。。。。,我觉得这个得加钱(小声)。我觉得可能行吧,但是我有点不舒服,今天感觉有点感冒,我要去医院检查“。
”啥,新冠?那你先去体检吧“。

我们来描述下上面那个场景的代码结构

故事中的A,B就是ConcreteProduct, Base就是Product, BaseFactory就是Creator, FactoryA就是ConcreteCreator
那么我们用代码重现structure

#include <iostream>

namespace DesignPatterns {
class Product {
 // ...
};

class ConcreteProductA : public Product {
 public:
  ConcreteProductA() {
    std::cout << "A Created" << std::endl;  
  }
  // ...
};

class ConcreteProductB : public Product {
 public:
  ConcreteProductB() {
    std::cout << "B Created" << std::endl;  
  }
  // 
};

class Creator {
 public:
   virtual Product* CreateProduct() = 0;
};

class ConcreteCreatorA : public Creator {
 public:
   virtual Product* CreateProduct() override {
      return new ConcreteProductA();
   }
};

class ConcreteCreatorB : public Creator {
 public:
   virtual Product* CreateProduct() override {
      return new ConcreteProductB();
   }
};

class FactoryTest {
 private:
   Creator* creator = nullptr;
   Product* product = nullptr;
 public:
   FactoryTest(Creator* crt) : creator(crt){}
   FactoryTest() = delete;
   bool Init() {
     if (creator) {
       this->product = creator->CreateProduct();
     }   
   }
};

}  // namespace DesignPatterns

int main(int argc, char* argv[]) {
  using namespace DesignPatterns;
  Creator* crt = new ConcreteCreatorA();
  FactoryTest bar(crt);
  bar.Init();
  return 0;
}

运行结果

要点总结

  1. Factory Method模式用于隔离类对象的使用者与具体类型之间的耦合关系。面对一个经常变化的具体类型,紧耦合关系会导致软件的脆弱。
  2. Factory Method模式通过面向对象的手法,将所要创建的具体对象工作延迟到子类,从而实现一种拓展而非修改的策略,较好的解决了这种紧耦合关系。
  3. Factory Method 模式解决了“单个对象”的需求变化,缺点在于要求创建方法与参数相同。
posted @ 2020-11-11 17:18  cyssmile  阅读(90)  评论(0编辑  收藏  举报