zoukankan      html  css  js  c++  java
  • 第4章 创建型模式—工厂方法模式(1)

    1. 简单工厂

    1.1 简单工厂的定义

    (1)提供一个创建对象实例的功能,而无须关心其具体实现

     

      ①Api接口:定义客户所需要的功能接口

      ②Impl:具体实现Api的实现类,可能会有多个

      ③SimpleFatory类:工厂,选择合适的实现类来创建Api接口对象

      ④Client:客户端,通过Factory来获取Api接口对象,然后面向Api接口编程。

    (2)思考简单工厂

      ①简单工厂的本质选择实现其重点在选择。工厂类内部的主要功能是“选择合适的实现类”来创建实例对象。

      ②简单工厂的目的:为客户端选择相应的实现,从而使得客户端和实现之间解耦。这样,具体实现发生了变化,也就不必变动客户端了,这个变化被简单工厂吸收和屏蔽掉了。

    (3)简单工厂命名的建议

      ①类名建议模块名称+Factory”。比如,用户模块的工厂就为UserFactory

      ②方法名通常为“get+接口名称”或者是“create+接口名称”。比如有一个接口名称为UserEbi,那么方法名称通常为getUserEbi或createUserEbi。

      ③不提倡将方法名称命名为“new+接口名称”,应该new在C++中是关键字,而且通过简单工厂获取的对象实例,并不一定每次都是要new一个新的实例。如果使用newUserEbi,会让人错觉,好象每次都是new一个新的实例一样。

    1.2 简单工厂的优缺点

    (1)简单工厂的优点

      ①帮助封装:简单工厂虽然简单,但是非常友好地帮助我们实现了组件的封装,让组件外部能真正的面向接口编程

      ②解耦,通过简单工厂,实现了客户端和具体实现类的解耦,客户端根本不知道具体是由谁来实现的,也不知道具体如何实现,只是通过工厂获取它需要的接口对象。

    (2)简单工厂的缺点

      ①可能增加客户端的复杂度,客户端通过参数来选择具体的实现类,那么就必须让客户端了解各个参数所代表的具体功能和含义,会增加使用难度,也部分暴露了其内部实现。

      ②不方便扩展子工厂,将工厂类的构造函数设有私有,使用静态方法也创建接口。所以也就不能通过写简单工厂类的子类来改变创建接口方法的行为了。不过,通常情况下是不需要为简单工厂创建子类的。

      ③当新增加接口的实现类时,须去修改工厂类的代码,这不符合开闭原则

      ④所有产品都是由一个工厂创建工厂类的职责较重,业务逻辑较为复杂具体产品与工厂类之间的耦合度高,严重地影响了系统的灵活性和扩展性。

    1.3 何时选用简单工厂

      ①如果要完全封装隔离具体实现,让外部只能通过接口来操作封装体。可以选用简单工厂,让客户端通过工厂来获取相应的接口,而无须关心具体的实现

      ②如果想把创建对象的职责集中管理控制,可以选用简单工厂

    【实例分析】利用简单工厂实现的计算器

     

    //创建型模式:简单工厂
    
    #include <stdio.h>
    
    //运算类(其它的加减乘法类从这里继承)
    class COperator
    {
    protected:
        double mFirst;
        double mSecond;
    public:
        void setFirst(double value){mFirst = value;}
        double getFirst(){return mFirst;}
        
        void setSecond(double value){mSecond = value;}
        double getSecond(){return mSecond;}
        
        virtual double getResult(){return 0;} 
    };
    
    //加法类
    class CAdd : public COperator
    {
    public:
        double getResult()
        {
            return mFirst + mSecond;
        }    
    };
    
    //减法类
    class CSub : public COperator
    {
    public: 
        double getResult()
        {
            return mFirst - mSecond;
        }    
    };
    
    //乘法类
    class CMul : public COperator
    {
    public:
        double getResult()
        {
            return mFirst * mSecond;
        }    
    };
    
    //除法类
    class CDiv : public COperator
    {
    public: 
        double getResult()
        {
             const double P = 0.000000000000001;
             if((-P < mSecond) && (mSecond< P)) //除数不能为0
             {
                return 0;
             }
                
            return mFirst / mSecond;
        }    
    };
    
    //简单工厂类
    class CSimpleFactory
    {
    public:
        /**
          *创建具体运算实现类对象的方法
          *@参数:从外部传入的选择条件(+、-、*、/)
          *@返回值:创建好的运算实现类对象
        */
        //将创建函数定义为静态成员函数,可以让客户端省去创建工厂类对象
        static COperator* createOperator(char cOperator)
        {
            COperator* oper = NULL;
            
            switch(cOperator)  //根据客户端传入的参数,选择创建具体的类
            {
            case '+':
                oper = new CAdd();
                break;
            case '-':
                oper = new CSub();
                break;
            case '*':
                oper = new CMul();
                break;
            case '/':
                oper = new CDiv();
                break;            
            }
            
            return oper;
        }
    };
    
    int main()
    {
        //客户端调用例子
        
        //客户端只需依赖COperator的接口类和工厂类,而无法知道具体的实现类
        //实现了客户端和具体实现类之间的解耦
        COperator* oper =  CSimpleFactory::createOperator('/');
        oper->setFirst(1);
        oper->setSecond(2);
        
        printf("%f + %f = %f
    ", oper->getFirst(),oper->getSecond(),oper->getResult());
        
        return 0;
    }
  • 相关阅读:
    FMDB 使用方法
    Masonry
    iOS请求服务器数据去空NSNull
    NSProgress
    根据图标名称动态设置TreeList图标
    控制显示行头列(Indicator)
    窗体内元素遍历-通用方法(DevExpress 中BarManager的遍历)
    BarManager相关使用
    C# 枚举变量
    dev TreeList 获取可视区域节点方法
  • 原文地址:https://www.cnblogs.com/5iedu/p/5491639.html
Copyright © 2011-2022 走看看