zoukankan      html  css  js  c++  java
  • 设计模式之简单工厂模式

    一、概述 

    工厂模式具体包括了简单工厂、工厂方法、抽象工厂,它们是按照从简单到复杂的顺序排列的,属于设计模式中的创建型,其中简单工厂并不属于GOF的23中模式。
      但是它是理解其它的工厂模式的一个很好的基础,所以很多人在讲述设计模式的时候会提到简单工厂模式。
      创建型模式关注的是对象的创建,创建型模式将创建对象的过程进行了抽象,也可以理解为将创建对象的过程进行了封装,作为客户程序仅仅需要去使用对象,而不再关心创建对象过程中的逻辑。

      优点:
      1)解决了代码中大量的new的问题,把new对象的操作集中封装到工厂类里面,这样一来,用工厂方法在一个类的内部创建对象通常比直接创建对象更灵活
      缺点:
      1)由于是简单的封装,所以此模式下对修改不封闭,新增产品时需要修改工厂类,违犯了开闭法则(OCP)。
            因为如果直接在工厂类的内部生产(new)所有的产品,当新增产品时,要去修改工厂类,封装性不好。 
      举例说明:
      简单工厂就是把某一类的产品做了规划,使其形成一个产品集合。但这些产品类不直接对外开放,而是通过它们的基类接口供外界调用,
      这就如同一个鞋厂,我们提货当然不能直接到生产部提货的, 你要知道生产部流水线很多的,他们只知道自己线上的型号,其它线上的型号可是一问三不知,何况作为一个外来人员,你要申请才能去参观哦。
      所以你就不要折腾了,这个鞋厂已经安排了销售部负责对外供货。如果我们需要什么型号的皮鞋,直接找销售部,销售部会帮你做好一切安排。
      现在很多代码都是没用使用工厂类,而是直接调用Prodcut类直接使用产品的,这就造成new来new去漫天飞,现在有了简单工厂模式,规划好产品,管理好产品,一切都在向良性方向发展。
     
      简而言之:  
      简单工厂两个类簇:一个类簇是Product,重在实现产品;一个类簇是Factory,重在是创建及管理产品。原则上,外界对产品的操作只能通过Factory,而不能直接对Product,这样保护了Product的秘密性。
     
      Product类负责完成各种各样的产品,对外面只提供有限的接口;它有2层结构:产品虚基类-产品子类
      Factory类负责创建产品,它有1层结构:简单工厂类

    二,类图:

    三,代码:

    SimpleFactory.h

    #pragma once
    
    //工厂类依赖于产品类,因为没有产品的工厂不能称之为工厂,所以有://工厂类---(调用)--->产品类
    #include "IProduct.h" 
    
    //下面的头文件其实应该放到cpp文件里面,之所以放在这里是为了更好诠释简单工厂模式(将它们一齐集中到h文件说明)
    #include "ConcreteProductA.h" 
    #include "ConcreteProductB.h"
    
    //工厂类:外层返回产品基类,内层生产(创建,new)具体的产品。
    //这就像是工厂向外界供货一样,客户需要什么产品,一个电话打到生产部,让生产部直接拿产品过来。即:一步(new)成型,并不会关注产品的制作过程。
    class CSimpleFactory
    {
    public:
    	CSimpleFactory() {};
    	~CSimpleFactory() {};
    
    public:
    	IProduct * CreateProduct(int nProductType);
    	IProduct *CreateProductA();
    	IProduct *CreateProductB();
    
    };
    

     SimpleFactory.cpp

    #include"SimpleFactory.h"
    
    IProduct *CSimpleFactory::CreateProduct(int nProductType)
    {
    	IProduct *ptr = 0;
    	
    	switch (nProductType)
    	{
    	case 0:
    		ptr = new CConcreteProductA();
    		break;
    
    	case 1:
    		ptr = new CConcreteProductB();
    		break;
    
    	default:
    		ptr = new CConcreteProductA();
    	}
    
    	return ptr;
    
    }
    
    IProduct *CSimpleFactory::CreateProductA()
    {
    	cout<<__FUNCTION__<<endl;
    	return new CConcreteProductA();
    }
    
    IProduct *CSimpleFactory::CreateProductB()
    {
    	cout<<__FUNCTION__<<endl;
    	return new CConcreteProductB();
    }
    

     IProduct.h

    #pragma once
    
    #include <stdio.h>
    #include <iostream>
    using namespace std;
    
    //这是一个产品虚基类:它的任务就是用来定型(抽象)所需求产品,抽象出它们的公共属性,然后让它的派生类一门心思地去完成自身的功能。
    //所以它并不依赖于任何业务相关的头文件,但有可能会依赖系统头文件,比如你使用了string,必须要包含string头文件
    //这个产品基类之所以存在是因为我们要为我们生产的产品抽象出了它们的公共属性,而这个公共属性是对外开放,供外部(比如说客户端程序)调用的。
    //外部调用时将以多态性进行操作,不会接触到产品内部的细节,这样就保证的产品的封闭性。
    
    class IProduct
    {
    protected:
    	IProduct();
    
    public:
    	virtual ~IProduct();
    
    public:
    	virtual void Function() = 0;
    };
    

     IProduct.cpp

    #include "IProduct.h"
    
    IProduct::IProduct(void)
    {
    
    }
    
    IProduct::~IProduct(void)
    {
    
    }
    

    ConcreteProductA.h

    #pragma once
    #include "IProduct.h" //CConcreteProductA(派生类) ----|> IProduct(基类)
    
    //实现产品的具体细节:基于产品功能需求(基类接口),具体化出功能A产品
    class CConcreteProductA :public IProduct
    {
    public:
    	CConcreteProductA();
    	virtual ~CConcreteProductA();
    
    	virtual void Function();
    };
    

     ConcreteProductA.cpp

    #include "ConcreteProductA.h"
    CConcreteProductA::CConcreteProductA(void)  
    {
    	cout<<__FUNCTION__<<endl;
    }
    
    CConcreteProductA::~CConcreteProductA(void) 
    {
    	cout<<__FUNCTION__<<endl;
    }
    
    void CConcreteProductA::Function() 
    {
    	cout<<__FUNCTION__<<endl;
    }
    

    ConcreteProductB.h

    #pragma once
    #include "IProduct.h" //CConcreteProductA(派生类) ----|> CProduct(基类)
    
    //实现产品的具体细节:基于产品功能需求(基类接口),具体化出功能B产品
    class CConcreteProductB :public IProduct
    {
    public:
    	CConcreteProductB(void);
    	virtual ~CConcreteProductB(void);
    
    	virtual void Function();
    };
    

    ConcreteProductB.cpp

    #include "ConcreteProductB.h"
    
    CConcreteProductB::CConcreteProductB(void)  
    {
    	cout<<__FUNCTION__<<endl;
    }
    
    CConcreteProductB::~CConcreteProductB(void) 
    {
    	cout<<__FUNCTION__<<endl;
    }
    
    void CConcreteProductB::Function() 
    {
    	cout<<__FUNCTION__<<endl;
    }
    

    main.cpp

    #include "SimpleFactory.h"
    #include <stdio.h>
    
    int main()
    {
    
    	CSimpleFactory fac;
    	IProduct *pProduct = fac.CreateProductA();
    	pProduct->Function();
    	delete pProduct;
    	pProduct = NULL;
    
    	pProduct = fac.CreateProductB();
    	pProduct->Function();
    	delete pProduct;
    	pProduct = NULL;
    
    	return 0;
    }
    

    四,运行结果:

    CSimpleFactory::CreateProductA
    CConcreteProductA::CConcreteProductA
    CConcreteProductA::Function
    CConcreteProductA::~CConcreteProductA
    CSimpleFactory::CreateProductB
    CConcreteProductB::CConcreteProductB
    CConcreteProductB::Function
    CConcreteProductB::~CConcreteProductB
    请按任意键继续. . .
     

  • 相关阅读:
    Eclipse启动Tomcat报错,系统缺少本地apr库
    Linux(Debian)下Maven的安装
    Debian ls 文件 文件夹颜色显示
    Mybatis3.0防止SQL注入
    MySql初始配置
    文档在线预览开源实现方案一:OpenOffice + SwfTools + FlexPaper
    Java多线程的信号量
    判断线程池中的线程是否全部执行完毕
    一个简单的死锁
    使用并发来提高数据抓取的效率
  • 原文地址:https://www.cnblogs.com/jacklikedogs/p/3807648.html
Copyright © 2011-2022 走看看