设计模式那点事--简单工厂模式

来源:互联网 发布:淘宝店铺外包合法吗 编辑:程序博客网 时间:2024/05/01 15:32

       工作几年后,每个程序员都会积累一定的编程经验,编程能力都会得到不同的提升。但是随着时间的推移,你会慢慢地发现,程序开发已经不仅仅是代码的简单堆砌,而是要开始考虑代码的复用扩展,性能优化,高效设计和执行效率等等问题了。为了要应付这些问题,设计模式应运而生。

         概念:

         简单工厂模式属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式。它实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。

         例子:

         一个鲜活简单的例子总能让人轻松地理解晦涩的概念。我们来看看一个关于汽车价格的简单工厂模式。

        我们知道,汽车的品牌和质量,决定了它的价格。就像宝马(BMW),法拉利(Ferrali)和奔驰(Benz)三辆汽车,它们的价格肯定是不一样的。那我们如果想要知道它的价格的话,可以询问销售人员等等。但是在计算机里,我们可不能直接问销售人员啊!

        对于它们来说,虽然各自价格不同,但是获取价格却是一种公共操作,是不同的算法,根据面向对象方法,应该要封装变化。于是,

可以创建一个抽象父类车类(Car),声明一个获取价格virtual GetPrice函数的接口。然后创建三个类:BMWFerraliBenz,分别继承于Car。通过继承关系,每个子类可以改写父类的GetPrice函数,从而获取自身的汽车价格。

        那么根据简单工厂模式的,我们需要一个工厂类,它根据传入的汽车编号,动态决定应该创建哪一款汽车的实例。汽车编号我们在客户端中传入即可,无需进行对象实例的创建,因为所有创建对象实例的操作都放在工厂类中。这样,以后增加其他品牌的汽车时,也只需增加一个汽车类,并且在工厂类中修改对象创建,对其它的汽车类代码没影响,保证了代码的灵活扩展。

        UML

 

        通过上面UML图可以看出,Car就是一个抽象汽车产品类,BMWFerraliBenz就是具体汽车产品类。

        代码:

#include <iostream>using namespace std; class Car{public:   float m_fPrice; public:   virtual float GetPrice()   {      return m_fPrice*1;   }}; class BMW:public Car{public:   float GetPrice()   {      return m_fPrice*3;   }}; class Ferrali:public Car{public:   float GetPrice()   {      return m_fPrice*11;   }}; class Benz:public Car{public:   float GetPrice()   {      return m_fPrice*6;   }}; class PriceFactory{public:   int m_iFlag; public:   Car* CreateCarPrice(int iFlag)   {      float fPrice=0.0;      Car* car = new Car;       switch (iFlag)      {       case 1:           return(new BMW);       break;       case 2:           return(new Ferrali);       break;       case 3:           return(new Benz);       break;       default:           return(new Car);       break;      }   }}; int main(){   float fPrice=0.0;   int iTag=0;    PriceFactory priceFactory;   Car* car;    cout<<"----简单工厂模式开始----"<<endl;   cout<<"BMW:1,Ferrali:2,Benz:3"<<endl;   cout<<"请输入您想要查询的汽车价格:";   cin>>iTag;    car = priceFactory.CreateCarPrice(iTag);   car->m_fPrice = 10000.0;   fPrice = car->GetPrice();
   delete car;
   car = NULL;
   cout<<"价格为:"<<fPrice<<endl;   cout<<"----简单工厂模式结束----"<<endl;    return 1;}

       发散:

       客户端中主要是把工厂类返回的汽车子类的实例赋给父类Car,从而实现调用相应子类的GetPrice函数,实现覆盖父类的虚函数GetPrice

       我们知道实现C++的多态有三种方法:函数重载,模板函数和虚函数。虚函数实现的多态称为动态多态,上面代码有以下特点:

       1、子类的对象转换给父类的对象如car = priceFactory.CreateCarPrice(iTag);,我们称为向上转型。它是安全的,自动完成,并且会丢失子类型的信息;

       2、为了解决子类型信息丢失的问题(子类对象转换给父类),父类必须实现了一个虚函数GetPrice

       3、子类有完全相同的GetPrice函数,覆盖重写父类的虚函数GetPrice,这样便能实现动态多态了(否则只能用指针或引用了)。

       优点:

       工厂类是整个模式的关键,,它根据客户端传入的汽车代码,决定究竟应该创建哪个汽车类的对象。通过使用工厂类,客户端可以从直接创建具体汽车对象的尴尬局面摆脱出来,仅仅需要确定生成什么汽车对象就可以了,而不必管这些对象究竟如何创建及如何组织的。明确了各自的职责和权利,有利于整个软件体系结构的优化。

      不足:

      由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类了。

      当系统中的具体产品类不断增多时候,可能会出现要求工厂类根据不同条件创建不同实例的需求.这种对条件的判断和对具体产品类型的判断交错在一起,很难避免模块功能的蔓延,对系统的维护和扩展非常不利。

     使用场景:

     1、工厂类负责创建的对象比较少;

     2、客户只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心;

     3、由于简单工厂很容易违反高内聚责任分配原则,因此一般只在很简单的情况下应用。

1 0
原创粉丝点击