设计模式之简单工厂模式、工厂模式、抽象工厂模式的对比
前言:
设计模式已经经历了很长一段时间的发展,它们提供了软件开发过程中面临的一般问题的最佳解决方案。学习这些模式有助于经验不足的开发人员通过一种简单快捷的方式来学习软件设计。
一般我们会说设计模式一共有23种,总体来说设计模式分为三大类:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
今天主要是分析 简单工厂模式、工厂模式和抽象工厂模式的区别,所以这里就简单介绍一下设计模式的概念。
网上的很多资料都是在阐述着:工厂模式的好处就是解耦。相信大家对解耦这个词也不陌生,那解耦究竟有什么好处呢?
- 1.为了提高内聚(Cohesion)和松耦合(Coupling),我们经常会抽象出一些类的公共接口以形成抽象基类或者接口。这样我们可以通过声明一个指向基类的指针来指向实际的子类实现,达到了多态的目的。这里很容易出现的一个问题 n 多的子类继承自抽象基类,我们不得不在每次要用到子类的地方就编写诸如 new ×××;的代码。这里带来两个问题:
客户程序员必须知道实际子类的名称(当系统复杂后,命名将是一个很不好处理的问题,为了处理可能的名字冲突,有的命名可能并不是具有很好的可读性和可记忆性,就姑且不论不同程序员千奇百怪的个人偏好了)。程序的扩展性和维护变得越来越困难。
- 2.还有一种情况就是在父类中并不知道具体要实例化哪一个具体的子类。这里的意思为:假设我们在类 A 中要使用到类 B,B 是一个抽象父类,在 A 中并不知道具体要实例化那一个 B 的子类,但是在类 A 的子类 D 中是可以知道的。在 A 中我们没有办法直接使用类似于 new ×××的语句,因为根本就不知道×××是什么。
以上两个问题也就引出了工厂模式的两个最重要的功能:定义创建对象的接口,封装了对象的创建;使得具体化类的工作延迟到了子类中。
对于工厂模式,为了使其能更好的解决多种情况的问题,将其分为三类:简单工厂模式(Simple Factory),工厂方法模式(Factory Method),抽象工厂模式(Abstract Factory)。GOAT 经常使用会遇到一些设计模式的使用,但是很少去细究里面的区别,这把就让我来大家分享一下,我认知中的这三种工厂模式。
简单工厂模式
我们把被创建的对象称为“产品”,把创建产品的对象称为“工厂”。如果要创建的产品不多,只要一个工厂类就可以完成,这种模式叫“简单工厂模式”。
结构定义:
是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式中包含的角色及其相应的职责如下:
工厂角色(Creator):这是简单工厂模式的核心,由它负责创建所有的类的内部逻辑。当然工厂类必须能够被外界调用,创建所需要的产品对象。
抽象(Product)产品角色:简单工厂模式所创建的所有对象的父类,注意,这里的父类可以是接口也可以是抽象类,它负责描述所有实例所共有的公共接口。
具体产品(Concrete Product)角色:简单工厂所创建的具体实例对象,这些具体的产品往往都拥有共同的父类。
定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。这满足创建型模式中所要求的“创建与使用相分离”的特点。
结构图如下
范例如下:
C++实现
- #include
- using namespace std;
-
- enum Product_Type
- {
- Product1_,
- Product2_,
- };
- class AbstractProduct //抽象(Product)产品角色
- {
- public:
- AbstractProduct() {}
- virtual ~AbstractProduct() {}
- virtual void Show() = 0;
- };
-
- class Product1 : public AbstractProduct //具体产品(Concrete Product)角色
- {
- private:
-
- public:
- Product1();
- ~Product1();
- void Show()
- {
- std::cout<< "product1"<
- }
- };
-
- Product1::Product1()
- {
- }
-
- Product1::~Product1()
- {
- }
- class Product2 : public AbstractProduct //具体产品(Concrete Product)角色
- {
- private:
-
- public:
- void Show()
- {
- std::cout<< "product2"<
- }
- };
- class Factory //工厂角色(Creator)
- {
- public:
- AbstractProduct *CreateProduct(Product_Type type)
- {
- switch (type)
- {
- case Product1_:
-
- return new Product1();
- case Product2_:
- return new Product2();
- default:
- return NULL;
- }
- }
- };
- int main(int argc, char **argv)
- {
- Factory *new_factory = new Factory();
- AbstractProduct *new_product1 = new_factory->CreateProduct(Product1_);
- new_product1->Show();
-
-
- AbstractProduct *new_product2 = new_factory->CreateProduct(Product2_);
- new_product2->Show();
-
- delete new_factory,new_product1,new_product2;
- new_factory = NULL;
- new_product1 = NULL;
- new_product2 = NULL;
- }
python实现
- #!/usr/bin/python3
-
- from enum import Enum
-
- ProducType = Enum(('ProducType'),('product1_','product2_','product_3'))
-
- class AbstractProduct(object):
- def show(self):
- pass
- class Product1(AbstractProduct):
- def show(self):
- print("Product1")
-
- class Product2(AbstractProduct):
- def show(self):
- print("Product2")
-
- class AbcFactory(object):
- def crete_product(self):
- pass
-
- class Factory(AbcFactory):
- def crete_product(self,type):
- product_type = {
- ProducType.product1_ : Product1(),
- ProducType.product2_ : Product2()
- }
- return product_type.get(type,None)
- if __name__ == "__main__":
- new_factory = Factory()
-
- product1 = new_factory.crete_product(ProducType.product1_)
- product1.show()
-
- product2 = new_factory.crete_product(ProducType.product2_)
- product2.show()
我们只需要调用不同的成员函数,工厂就帮我们实例化出想要的对象,利用上转型对象,返回父类的方式实现了结果。可以发现简单工厂模式代码简单,但不符合OCP(面向对象设计的基本原则之一 OCP(开闭原则):一个软件的实体应当对扩展开放,对修改关闭)。
总结 :
简单工厂模式最大的优点在于工厂类中可以判断客户的的选择来动态实例化相关的类,对于客户端来说,去除了具体产品的依赖。
缺点就是:很明显工厂类集中了对所有实例创建的逻辑,如果我们要新增子类或者改变方法的话,就得每次都修改工厂类里面的代码,工厂类中的代码就会十分臃肿,这就等于说我们不进开放了扩展,还开放了修改,这样就违反了开放-封闭原则。
你可能在不知不觉中已经用到过这种模式了,但简单工厂模式并不属于23种设计模式之一,下面介绍他的改进版本:工厂方法模式。
工厂模式
工厂方法模式是一种创建型设计模式, 其在父类中提供一个创建对象的方法, 允许子类决定实例化对象的类型。
工厂方法模式的结构组成:
抽象工厂类厂(AbstractFactory):工厂方法模式的核心类,提供创建具体产品的接口,由具体工厂类实现。
具体工厂类(Producer):继承于抽象工厂,实现创建对应具体产品对象的方式。
抽象产品类(Factory):它是具体产品继承的父类(基类)。
具体产品类(Factory1):具体工厂所创建的对象,就是此类。
C++实现
- #include
- using namespace std;
- class AbstractProduct
- {
- public:
- AbstractProduct() {}
- virtual ~AbstractProduct() {}
- virtual void Show() = 0;
- };
-
- class Product1 : public AbstractProduct
- {
- private:
-
- public:
- Product1();
- ~Product1();
- void Show()
- {
- std::cout<< "product1"<
- }
- };
-
- Product1::Product1()
- {
- }
-
- Product1::~Product1()
- {
- }
- class Product2 : public AbstractProduct
- {
- private:
-
- public:
- void Show()
- {
- std::cout<< "product2"<
- }
- };
- class Factory
- {
- public:
- virtual ~Factory(){};
- virtual AbstractProduct *CreateProduct() = 0;
- };
- class Factory1 : Factory
- {
- public:
- AbstractProduct * CreateProduct(void)
- {
- return new Product1();
- }
-
- };
- class Factory2 :Factory
- {
- public:
- AbstractProduct * CreateProduct(void)
- {
- return new Product2();
- }
- };
- int main(int argc, char **argv)
- {
- Factory1 *new_factory = new Factory1();
- AbstractProduct *new_product1 = new_factory->CreateProduct();
- new_product1->Show();
- delete new_factory;
- new_factory = NULL;
-
- Factory2 * new_factory2 = new Factory2();
- AbstractProduct *new_product2 = new_factory2->CreateProduct();
- new_product2->Show();
- delete new_factory2;
- new_factory2 = NULL;
- }
python实现
- #!/usr/bin/python3
-
-
- class AbstractProduct(object):
- def show(self):
- pass
- class Product1(AbstractProduct):
- def show(self):
- print("Product1")
-
- class Product2(AbstractProduct):
- def show(self):
- print("Product2")
-
- class Factory(object):
- def create_product(self):
- pass
- class Factory1(Factory):
- def create_product(self):
- return Product1()
-
- class Factory2(Factory):
- def create_product(self):
- return Product2()
-
- if __name__ == "__main__":
- new_product1 = Factory1().create_product()
- new_product1.show()
- new_product2 = Factory2().create_product()
- new_product2.show()
工厂方法模式优缺点
- 1.你可以避免创建者和具体产品之间的紧密耦合。
- 2.单一职责原则。你可以将产品创建代码放在程序的单一位置, 从而使得代码更容易维护。
- 3.开闭原则。无需更改现有客户端代码, 你就可以在程序中引入新的产品类型。
- 4.应用工厂方法模式需要引入许多新的子类, 代码可能会因此变得更复杂。最好的情况是将该模式引入创建者类的现有层次结构中。
抽象工厂模式
抽象工厂模式是一种创建型设计模式, 它能创建一系列相关的对象, 而无需指定其具体类。是更多一重的工厂模式中。
结构定义(类似工厂模式):
抽象工厂类厂(AbstractFactory):工厂方法模式的核心类,提供创建具体产品的接口,由具体工厂类实现。
具体工厂类(Producer):继承于抽象工厂,实现创建对应具体产品对象的方式。
抽象产品类(Factory):它是具体产品继承的父类(基类)。
具体产品类(Factory1):具体工厂所创建的对象,就是此类。
结构图如下
C++实现
- #include
- using namespace std;
- class AbstractProductA
- {
- public:
- AbstractProductA() {}
- virtual ~AbstractProductA() {}
- virtual void Show() = 0;
- virtual void Disp() = 0;
- };
-
- class ProductA1 : public AbstractProductA
- {
- private:
-
- public:
- ProductA1(){}
- ~ProductA1(){}
- void Show()
- {
- std::cout<< "productA1 show"<
- }
- void Disp()
- {
- std::cout<< "productA1 Disp"<
- }
- };
- class ProductA2: public AbstractProductA
- {
- private:
-
- public:
- ProductA2(){}
- ~ProductA2(){}
- void Show()
- {
- std::cout<< "productA2 show"<
- }
- void Disp()
- {
- std::cout<< "productA2 Disp"<
- }
- };
- class AbstractProductB
- {
- public:
- AbstractProductB() {}
- virtual ~AbstractProductB() {}
- virtual void Show() = 0;
- virtual void Disp() = 0;
- };
-
- class ProductB1 : public AbstractProductB
- {
- public:
- void Show()
- {
- std::cout<< "productB2 show"<
- }
- void Disp()
- {
- std::cout<< "productB2 Disp"<
- }
- };
- class Factory
- {
- public:
- virtual AbstractProductA *CreateProductA(void) = 0;
-
- virtual AbstractProductB *CreateProductB(void) = 0;
- };
- class Factory1 :Factory
- {
- public:
- AbstractProductA * CreateProductA(void)
- {
- return new ProductA1();
- }
- AbstractProductB * CreateProductB(void)
- {
- return new ProductB1();
- }
- };
- class Factory2:Factory
- {
- public:
- AbstractProductA * CreateProductA(void)
- {
- return new ProductA2();
- }
- AbstractProductB * CreateProductB(void)
- {
- return NULL;
- }
- };
-
- int main(int argc, char **argv)
- {
- Factory2 *new_factory2 = new Factory2();
- AbstractProductA *new_productA2 = new_factory2->CreateProductA();
- new_productA2->Show();
-
- Factory1 *new_factory1 = new Factory1();
- AbstractProductB *new_productB1 = new_factory1->CreateProductB();
- new_productB1->Show();
- }
- python 实现
python 实现
- #!/usr/bin/python3
-
-
- class AbstractProductA(object):
- def show(self):
- pass
- def disp(self):
- pass
-
- class ProductA1(AbstractProductA):
- def show(self):
- print("ProductA1 show")
- def disp(self):
- print("productA1 disp")
- class ProductA2(AbstractProductA):
- def show(self):
- print("ProductA2 show")
- def disp(self):
- print("productA2 disp")
-
-
- class AbstractProductB(object):
- def show(self):
- pass
-
- def disp(self):
- pass
- class ProductB1(AbstractProductB):
- def show(self):
- print("ProductB1 show")
- def disp(self):
- print("productB1 disp")
-
- class ProductB2(AbstractProductB):
- def show(self):
- print("ProductB2 show")
- def disp(self):
- print("productB2 disp")
-
- class Factory(object):
- def crete_product1(self):
- pass
- def crete_product2(self):
- pass
-
- class FactoryA(object):
- def crete_product1(self):
- return ProductA1()
-
- def crete_product2(self):
- return ProductA2()
-
- class FactoryB(object):
- def crete_product1(self):
- return ProductB1()
-
- def crete_product2(self):
- return ProductB2()
-
- if __name__ == "__main__":
- new_factory = FactoryA()
- new_product1 = new_factory.crete_product1()
- new_product1.show()
-
- new_product2 = new_factory.crete_product2()
- new_product2.disp()
抽象工厂模式优缺点
- 1.你可以确保同一工厂生成的产品相互匹配。可以避免客户端和具体产品代码的耦合。
- 2.单一职责原则。你可以将产品生成代码抽取到同一位置, 使得代码易于维护。
- 3.开闭原则。向应用程序中引入新产品变体时, 你无需修改客户端代码。
- 4.由于采用该模式需要向应用中引入众多接口和类, 代码可能会比之前更加复杂。
本文转载自微信公众号「羽林君」,可以通过以下二维码关注。转载本文请联系羽林君公众号。
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341