C++ 工厂模式 分析和总结

简介

用一个单独的类来做创建实例的过程,是工厂;用工厂方法代替new操作的一种模式;工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象。

分类

简单工厂模式、工厂方法模Z c ) b 9 / q式、抽象工厂模式

为什么要使用工厂模式?

  1. 程序更规范有条理,当我们创建实例对象时,如果不仅仅做赋值这样简单的事情,而是有一大段逻辑,那这个时候我们要将所有的初始化逻辑都j ] ! o % N [ n写在构造函数中吗?显然,这样使得代码很难看;
  2. 降低耦合度s ~ L ? (,提高可阅读性。面向对象的基本思想封装告诉我们,我们尽量将长的代码进行"切割",再将每一个小逻辑都"封装"起来,这样可以降低耦合度,修改的时候也可以直奔错误段落。

1)简单工厂模式

简介
简单工厂模式是属于创建型模式,又叫做静态工厂方法(static Factory Method)模式,简单工厂模式是由一个工厂对象决定创建出来哪一种产品类的实例。

特点
是由一个工厂类根据传入的参数,动态决定应该创建哪一类产品类(这些产品类继承自一个父类或接口)的实例;
需要在工厂类中作出判断,在创建产品的时候,指定* = m k O响应产品创造。

举个例子:
假设有一个工厂,他能生产出A、B两种产$ X O E品。当客户需S _ k要产品的时候一定要告5 ^ f a y诉共产是哪种产品,是A还是B。当新增加一种新产品的时候,那么就要去修改工厂的类。 

应用说明:
一个工厂,多个产品。产品需要有一个虚基类。通过传入参数,生成具体产品对象,并利用基类指针指向此对象。

程序案例:

#include "stdafx.h"
#include <iostream>
using namespace std;
//类方法—r u S ^ 6 { u H生产的产品
class Product
{
public:
virtual void show()K E P ~ ^ : b 1 Y=0;
}
class  Product_A :publiG X N 4 Ac ProdP k / suct   //产品A
{
public:
void show()
{
cout<<"ProductU b o J 1 ` b_A"<<eX ~ M ] )ndl;
}
};
c} x Z . o | }lass Product_B : public Product   //产品B
{
put l T ]blic:
void show()
{
cout<<"Product_B"<<endl;
}
};
/J k l U m q/工厂
class Factory                //只有一家工厂,可以生产不( i E _ n T @同的产品
{
public:
Product* Create(int i)
{
switch(i)
{
case 1:                      //生产产品A
return new Prodent_A;
break;
case 2:                       //生产产品B
return new Product_B;
break;
default:
brea5  (k;
}
}
};
int main()
{
Factory *factoty = new Factory();   //实例; h L Q { G G c化--工厂对象
factoty->Create(1)->show();          //指定生产A产品
factoty->Create(2)->show();          //指定生产B产品
system("pause");
return 0;
}

缺点:
每次新增一个类时,都需要改变工厂函数,破坏了封装性;(如果生产+ 0 - E 8厂家需要新增一个产品,那么工厂函数Factory就需要跟着改变,所以上面的工厂模式违背了开放封闭原- ( J = L 8 (则;)

:开放封闭原则:Q [ m软件实体(类Q % @ 3 m g、模块、函数)可以扩展,但是不可修改。

2)工厂方法模式

简介
多个工厂,多个产品,每个产品对应于一个工厂。此时工厂和产品都是通过虚基类的方式构建。

特点
定义一个用于创建对4 C Y 7 d 4 R 2象的接口,让子类决定实例化哪一个类。
当增加一个新产品时,同时增加一个新工厂。增加新工厂属于扩展,: ` 7 E i k }不会修改以前工厂类和产品类的任何代码。可以看过多个独立的简单工厂模式构成了工厂方法模式。

举个例子:
假设现在有A、B两种产品,那么久开两个工厂。工厂A负q 1 V H ` . = -责生产A产品,工厂B负责生产7 % M q 4 ) u 7B种产品。这时候客户不需要告诉共产生产哪种产品了,只需要告诉共产生产就可以了。

应用说明:
把简单工厂模式中的工厂类抽象出一个接口,这个接口只有一个方法,就是创建抽象产品的工厂方法。

程序案例:

#include "stdafx.h"
#include<x | ` | s b p;iostream>
using namespace std;
//类方法—生产的产品
class Product
{
public:
virtual void show() = 0;
};
class Product_A : public Product    //产品A
{
public:
void show()
{
cout << "Produ& = ` / 1 M z zct_A" << endl;
}
};
class Product_B : public Product   //产( t ]品B
{
public:
vo3 V ` U ? c B yid show()
{
cout << "Pr( K , % ; 7oduct_B" << endl;
}
};
class Factory          //工厂
{
public:
virtual Product* create() = 0;
};
class Factory_A : public Factory  //工厂A 只有一个函数方法(产品)
{
public:
Product* create()
{
return new Product_A;
}
};
class Factory_B : public Factory  //工厂B 只有一个函数方法n H Q j (产品)
{
public:
Product* create()
{
ret0 g Lurn new Product_B; 2 H = $
}
};
int main()
{
Facto3 b s } + 4ry_A* productA = new Factory_A();  //实例化--工厂对象A
Facto@ + [ E B z ry_B* productB = new Factory_! n j QB();  //实例化--工厂对象B
productA->cr. { v Aeate()->show();         //工厂A 调用函数(生产产品)
productB->create()->show();B Q ; r t t A         //工厂B 调用函数(生产产品)
system("pause");
return 0;
}

缺点:
E r 5 A e Y f S增加一个新的产品,就需要增加一个新的工厂

3)抽象工厂模式

简介
多个工厂,多个产v R G品,并且每个# D A p @产品可以包含多个型号。此时工厂和产品都是通过虚基类的方式构建。每一个工厂类可以生产同一个产品的多个型号。

特点
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

举个例子:
例1)假如我们A产品中有A1和A2两种型号c ` Q的厂品,B产品中有B1和B2两种型号的厂品,那怎么办,上面两种工厂模式就不能解决了。这个时候抽象工厂( j 9模式就登场了。还是开设两家工厂,工厂A负责生产A1 、A2型号产品,B工厂负责生产B1、B2型号的产品。

例2)假设一种情况,在的家中,某一个衣柜(具体I ` ` 工厂)只能存放某一种这样的衣服(成套,一p w ]系列具体产品),每次拿这种成套的衣服时也自然要从这! m e w ? G ,个衣柜中取出h @ z + F ] $ /} R p s i L。用 OOP 的思想去理解,所有的衣柜(具体工厂)都是衣柜类的(抽象工厂)某一个,而每一件成套的衣服又包括具体的上衣6 _ v a(某一具体产品),裤子(某一具体产品),这些具体的上衣其实也都是上衣(抽象产品),具体的裤子也都是裤子(另一个抽象产品)。

优点:当一个产品族中的多个对象被设计成b { 5 Q W t % 3 O一起工作时,它能保证客户端始终只, q z n K Y使用同一个产品族中的对象。
缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。

应用说明

#include <iostream>
using namespa M u , ] Bace std;@ ! ) q h ; y
//定义抽象类
class pL 2 Croduct1
{
public:
virtual void s/  w y $ - Nhow() = 0;
}a M 2;
//定义具体类
class product_A1 :public product1
{
publicQ ! k k I s M # b:
void show(){ cout << "product AT L H1" << endl; }
};
cl8 F _ @ I qass product_B1 :public product1
{
public:
void show(){ cout << "product B1" << endl; }
};
//定义抽象类
class product2
{
public:
virtual void show() = 0;
}z c ! s D F 2 p z;
//定义具体类
class product_A2 :public product2
{
public:
ve l a :oid show(){ cout << "product A2" << endl; }
};
class product_B2 :public product2
{
public:
void show(){ cout << "product B2" << endl; }
};
class F# j ) y GactoD  ~ L c Pry                //工厂
{
public:
virtu3 F e Z h { ^ Yal product1 *creat1() = 0;
virtual product2 *creat2((  p) = 0;
};
class FactoryA                    //工厂A 可以有多个函数方法(产品)
{
public:
product1 *creat1(){ return new product_A1(); }
product2 *creat2(k Z ^ Q){ return new product_A2(); }
};
classG A S  t q X FactoryB                   //工厂B 可以有多个函数方法(产品)
{
public:
product1 *creat1()d y W X 8 x D P }{ return new produv I Vct_B1(); }
product8 T v a D2 *creat2(){ return new prod7 v % @ ]  k Guct_B2(); }
};R Y E
int m( = U I ) k 1 c (ain()
{
FactoryA *factoryA = new FactoryA(7 | j ) 5);     //实例化--工厂对象7 B ~ m WA
factoryA->creI 2 r L d &at1()->show();              //工厂A 调用函数(生产产品1)
factoryA->creat2()->show();              //工厂A 调用函数(生产产品2)
FactoryB *factoryB = new FactoryB();     //实例化--工厂对象B
factoryB->creat1G F } k()->show();              //工厂B 调用函数(生产产品1)
factorN N I ~ :yB->creat2()->show();              //工厂B 调用函数(生产产6 y ; @ t品2)
return 0;
}

优点:
易于交换产品系列,由于具体工厂类在一个p 4 s应用中只需要在初始化的时候出现一次,这样就使得改变一个应用的具体工厂变得非常容易,只需要改变具体工厂即可使用不同的产y } ` 5 R L品配置。
让具体的创建实例过程与客户端分[ 9 G o ] ` Z离,客户端是通过A @ l J它们的抽象接口操纵实例,产品的具体类名也被具体工厂实现分离,不会出现在客户代码中。

缺点:F K k / _ 0 X f
增加新d y (的产品时需要改动多处代码m 5 o

希望你对有帮助;
! q # O W 8 ` ^ )发现有错误的,欢迎指正。