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

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

         概念:

         简单工厂模式属于创建型模式,又叫做静态工厂方法(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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
软件秘笈:设计模式那点》郑阿奇(编者) -电子工业出版社 在第1章软件设计模式概述后,从第2章到第24章诠释23个软件设计模式。 1 设计模式概述 1.1 计算机软件的发展现状 1.2 引入设计模式的必要性 1.3 软件设计遵循的基本原则 1.3.1 内聚、低耦合 1.3.2 面向抽象编程 1.3.3 多用组合少用继承 1.3.4 “开-闭”原则 1.4 设计模式概述 1.4.1 什么是设计模式 1.4.2 为什么需要设计模式 1.4.3 如何正确应用设计模式 1.5 设计模式的分类 1.5.1 创建型模式 1.5.2 结构型模式 1.5.3 行为型模式 1.6 学会归纳和总结 第一部分 创建型模式 2 曹操献刀:工厂方法模式 2.1 三国故之曹操献刀 2.2 模式定义 2.3 故中的模式分析 2.3.1 故中的角色 2.3.2 抽象化分析方法 2.3.3 工厂方法模式的静态建模 2.4 故的工厂方法模式实现 2.4.1 建立产品 2.4.2 建立工厂 2.4.3 故情节的历史重现 2.4.4 用八星宝刀来考验模式 2.5 设计原则 2.6 使用场合 2.7 本章要点 3 肯德基:抽象工厂模式 3.1 发生在肯德基的故 3.2 模式定义 3.3 故中的模式分析 3.3.1 故中的角色 3.3.2 抽象化分析 3.3.3 抽象工厂模式的静态建模 3.4 故的抽象工厂模式实现 3.4.1 抽象食物的建立 3.4.2 建立不同食物的抽象基类 3.4.3 创建具体的食物 3.4.4 建立工厂 3.4.5 创建客户类 3.4.6 故情节的展现 3.5 设计原则 3.6 使用场合 3.7 本章要点
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值