• 3.3FactoryMethod——工厂方法


    意图:

    定义一个用于创建对象的接口,让子类决定实例化哪一个类。FactoryMethod使一个类的实例化延迟到其子类。

    其实在抽象工厂模式中,经过改进后的模式就是工厂方法模式,所以不多说了,上UML图。


    通过工厂方法模式的类图可以看到,工厂方法模式有四个要素:

    1.工厂接口。工厂接口是工厂方法模式的核心,与调用者直接交互用来提供产品。在实际编程中,有时候也会使用一个抽象类作为与调用者交互的接口,其本质上是一样的。

    2.工厂实现。在编程中,工厂实现决定如何实例化产品,是实现扩展的途径,需要有多少种产品,就需要有多少个具体的工厂实现。

    3.产品接口。产品接口的主要目的是定义产品的规范,所有的产品实现都必须遵循产品接口定义的规范。产品接口是调用者最为关心的,产品接口定义的优劣直接决定了调用者代码的稳定性。同样,产品接口也可以用抽象类来代替,但要注意最好不要违反里氏替换原则。

    4.产品实现。实现产品接口的具体类,决定了产品在客户端中的具体行为。

    前文提到的简单工厂模式跟工厂方法模式极为相似,区别是:简单工厂只有三个要素,他没有工厂接口,并且得到产品的方法一般是静态的。因为没有工厂接口,所以在工厂实现的扩展性方面稍弱,可以算作工厂方法模式的简化版

    举例说明:

    还是举生产产品的例子吧。一个工厂生产A,B两种产品,以后还可能会拓展生产C产品,怎么安排类的设计模式使得以后的拓展或者用户额调用更加方便——工厂方法模式。

    //定义工厂方法所创建的对象的接口
    #ifndef _PRODUCT_H
    #define  _PRODUCT_H
    
    class Product
    {
    protected:
    	Product(){}
    public:
    	virtual ~Product(){}
    	virtual void function() = 0;
    };
    #endif
    
    //实现Product接口
    #ifndef _CONCRETE_PRODUCT_A_H
    #define _CONCRETE_PRODUCT_A_H
    
    #include "Product.h"
    #include <iostream>
    using namespace std;
    
    class ConcreteProductA : public Product
    {
    public:
    	ConcreteProductA()
    	{
    		cout<<"创建产品A"<<endl;
    	}
    
    	virtual ~ConcreteProductA()
    	{
    		cout<<"销毁产品A"<<endl;
    	}
    
    	virtual void function()
    	{
    		cout<<"这是产品A的功能"<<endl;
    	}
    
    };
    #endif
    
    //实现Product接口
    #ifndef _CONCRETE_PRODUCT_B_H
    #define _CONCRETE_PRODUCT_B_H
    
    #include "Product.h"
    #include <iostream>
    using namespace std;
    
    class ConcreteProductB : public Product
    {
    public:
    	ConcreteProductB()
    	{
    		cout<<"创建产品B"<<endl;
    	}
    
    	virtual ~ConcreteProductB()
    	{
    		cout<<"销毁产品B"<<endl;
    	}
    
    	virtual void function()
    	{
    		cout<<"这是产品B的功能"<<endl;
    	}
    
    };
    #endif
    
    //声明工厂方法,该方法返回一个Product类型的对象
    #ifndef _CREATER_H
    #define  _CREATER_H
    
    class Creator
    {
    public:
    	Creator(){}
    	virtual ~Creator(){}
    	virtual Product *CreateProduct(int type=0) = 0;//参数化工厂方法
    };
    #endif
    
    //重定义工厂方法以返回一个ConcreteProduct实例
    #ifndef _CONCRETE_CREATOR_H
    #define  _CONCRETE_CREATOR_H
    
    #include "ConcreteProductA.h"
    #include "ConcreteProductB.h"
    #include "Product.h"
    class ConcreteCreator : public Creator
    {
    public:
    	ConcreteCreator(){}
    	virtual ~ConcreteCreator(){}
    	virtual Product *CreateProduct(int type)
    	{
    		Product *product;
    		switch(type)
    		{
    		case 0:
    			product = new ConcreteProductA();
    			break;
    		case 1:
    			product = new ConcreteProductB();
    			break;
    		default:
    			product = new ConcreteProductA();
    			break;
    		}
    		return product;
    	}
    
    };
    #endif
    
    客户端程序:
    #include "Product.h"
    #include "ConcreteProductA.h"
    #include "ConcreteProductB.h"
    #include "Creator.h"
    #include "ConcreteCreator.h"
    
    int main(int argc, char **argv)
    {
    	Creator *c = new ConcreteCreator();
    	Product *p = c->CreateProduct(0);
    	p->function();
    	delete p;
    	delete c;
    
    	system("pause");
    	return 0;
    }
    

    当我们的系统需要增加其他新的对象时,我们只需要添加一个具体的产品和它的创建工厂即可,不需要对原工厂进行任何修改,这样很好地符合了“开闭原则”。

    工厂方法适用场景

    1、一个类不知道它所需要的对象的类。在工厂方法模式中,我们不需要具体产品的类名,我们只需要知道创建它的具体工厂即可。

    2、一个类通过其子类来指定创建那个对象。在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。

    3、将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定。


  • 相关阅读:
    any、some、all for sql
    Date CONVERT() 函数
    Config Database
    移动master 数据库
    使用 OpenRowSet 和 OpenDataSource 访问 Excel 972007
    动态管理视图和函数
    SQL Server 2005 Merge Replication Step by Step Procedure
    系统试图(返回表所有记录数及所有的 identity 列)
    js if without curly brackets bug All In One
    Web3 All In One
  • 原文地址:https://www.cnblogs.com/snake-hand/p/3181602.html
Copyright © 2020-2023  润新知