大话设计模式:工厂模式
2016-07-16 16:39
351 查看
有了前面介绍的简单工厂模式,为什么又会出来一个工厂模式呢?它们之间的区别又在哪里?工厂模式的精髓又在哪里?
工厂方法模式: 定义一个用于创建对象的接口,主要解决了让子类决定实例化哪一个类,而不是像简单工厂一样,让工厂来直接决定实例化哪一个产品。工厂方法模式是对简单工厂模式的稍微改进。工厂方法模式的用意是定义一个创建产品对象的工厂接口,将实际工作推迟到子类中。
还以书上的计算器为例:
工厂模式主要包括以下几个模块:
(1)抽象工厂:一个接口,子类的具体工厂实现该接口(AbstructFectory);
(2)具体工厂:具体工厂负责生产具体的产品(AddFactory);
(3)抽象产品:具体产品继承该抽象产品;(Operation);
(4)具体产品:生产具体产品,实际的功能操作(OperationAdd);
优点:使程序模块化更高,低耦合。可维护性更强。
(1)与简单工厂模式相比,制造产品的工厂类不再只有一个,而是每种具体产品类都对应一个生产它的具体工厂类(OperationAdd--AddFactory)。而这些具体工厂类的共同特征再被提取出来形成一个抽象产品类(Operation),这些具体产品类都继承自这个抽象产品类。
(2)当需要增加一种产品的时候,需要做的是:
a.增加一种继承自抽象产品的具体产品类(开根号的运算类OperationSquart);
b.增加一种继承在抽象工厂的具体工厂类(SquartFactory),
c.更改客户端。而不需要在简单工厂模式中那样更改工厂类的switch。
因为当我们在要添加一个M的N次方的功能的时候,我们只需要添加一个相应的工厂类和一个相应的运算类就可以了,我们不需要再去修改原有的工厂类了。这样在添加功能的过程中,整个工厂和产品体系没有修改的变化,而只是有了扩展的变化,这样就不会影响原有的功能的运行,这样就符合了另一个非常重要的开放-封闭(对于扩展是开放的,对于修改使关闭的)原则精神。
缺点:
(1)只能生产同一种类型的产品,产品结构单一,所有的具体产品都继承产品抽象类;
(2)简单工厂模式里我们是通过修改工厂类你的switch-case来选择实例化那个对象,但是这里我们虽然不需要修改工厂类了,但是我们需要修改客户端,也就是说工厂方法将内部的逻辑判断移动到了客户端。本来是要修改工厂类的,但是现在改成了修改客户端。
其uml图如下:
![](https://img-blog.csdn.net/20160716163818637?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
具体实现代码:
#include <iostream>
using namespace std;
//抽象产品类
class Operation
{
protected:
double numberA;
double numberB;
public:
double getA()
{
return numberA;
}
double getB()
{
return numberB;
}
void setA(double number)
{
numberA=number;
}
void setB(double number)
{
numberB=number;
}
virtual double GetResult()
{
double result=0;
return result;
}
};
//下面是四个具体产品类,只能是同一类的产品;
class OperationAdd:public Operation
{
public:
double GetResult()
{
double result=0;
result=numberA+numberB;
return result;
}
};
class OperationSub:public Operation
{
public:
double GetResult()
{
double result=0;
result=numberA-numberB;
return result;
}
};
class OperationMul:public Operation
{
public:
double GetResult()
{
double result=0;
result=numberA*numberB;
return result;
}
};
class OperationDiv:public Operation
{
public:
double GetResult()
{
double result=0;
if(numberB!=0)
result=numberA/numberB;
return result;
}
};
//抽象工厂类
class AbstractFactory
{
public:
virtual Operation* createOperation()
{
return new Operation;
}
};
//下面是四个具体工厂类,分别用于产生四个具体产品
class AddFactory:public AbstractFactory
{
public:
Operation* createOperation()
{
Operation* oper=new OperationAdd;
return oper;
}
};
class SubFactory:public AbstractFactory
{
public:
Operation* createOperation()
{
Operation* oper=new OperationSub;
return oper;
}
};
class MulFactory:public AbstractFactory
{
public:
Operation* createOperation()
{
Operation* oper=new OperationMul;
return oper;
}
};
class DivFactory:public AbstractFactory
{
public:
Operation* createOperation()
{
Operation* oper=new OperationDiv;
return oper;
}
};
//客户端
int main()
{ //客户端判断具体实例化那个子工厂,那个具体产品;
AbstractFactory* af=NULL;
af=new AddFactory();
Operation* oper=NULL;
oper=af->createOperation();
oper->setA(3);
oper->setB(2);
cout<<oper->GetResult()<<endl;
if(af!=NULL)
{
delete af;
af=NULL;
}
if(oper!=NULL)
{
delete oper;
oper=NULL;
}
system("pause");
return 0;
} 运行结果:
工厂方法模式: 定义一个用于创建对象的接口,主要解决了让子类决定实例化哪一个类,而不是像简单工厂一样,让工厂来直接决定实例化哪一个产品。工厂方法模式是对简单工厂模式的稍微改进。工厂方法模式的用意是定义一个创建产品对象的工厂接口,将实际工作推迟到子类中。
还以书上的计算器为例:
工厂模式主要包括以下几个模块:
(1)抽象工厂:一个接口,子类的具体工厂实现该接口(AbstructFectory);
(2)具体工厂:具体工厂负责生产具体的产品(AddFactory);
(3)抽象产品:具体产品继承该抽象产品;(Operation);
(4)具体产品:生产具体产品,实际的功能操作(OperationAdd);
优点:使程序模块化更高,低耦合。可维护性更强。
(1)与简单工厂模式相比,制造产品的工厂类不再只有一个,而是每种具体产品类都对应一个生产它的具体工厂类(OperationAdd--AddFactory)。而这些具体工厂类的共同特征再被提取出来形成一个抽象产品类(Operation),这些具体产品类都继承自这个抽象产品类。
(2)当需要增加一种产品的时候,需要做的是:
a.增加一种继承自抽象产品的具体产品类(开根号的运算类OperationSquart);
b.增加一种继承在抽象工厂的具体工厂类(SquartFactory),
c.更改客户端。而不需要在简单工厂模式中那样更改工厂类的switch。
因为当我们在要添加一个M的N次方的功能的时候,我们只需要添加一个相应的工厂类和一个相应的运算类就可以了,我们不需要再去修改原有的工厂类了。这样在添加功能的过程中,整个工厂和产品体系没有修改的变化,而只是有了扩展的变化,这样就不会影响原有的功能的运行,这样就符合了另一个非常重要的开放-封闭(对于扩展是开放的,对于修改使关闭的)原则精神。
缺点:
(1)只能生产同一种类型的产品,产品结构单一,所有的具体产品都继承产品抽象类;
(2)简单工厂模式里我们是通过修改工厂类你的switch-case来选择实例化那个对象,但是这里我们虽然不需要修改工厂类了,但是我们需要修改客户端,也就是说工厂方法将内部的逻辑判断移动到了客户端。本来是要修改工厂类的,但是现在改成了修改客户端。
其uml图如下:
具体实现代码:
#include <iostream>
using namespace std;
//抽象产品类
class Operation
{
protected:
double numberA;
double numberB;
public:
double getA()
{
return numberA;
}
double getB()
{
return numberB;
}
void setA(double number)
{
numberA=number;
}
void setB(double number)
{
numberB=number;
}
virtual double GetResult()
{
double result=0;
return result;
}
};
//下面是四个具体产品类,只能是同一类的产品;
class OperationAdd:public Operation
{
public:
double GetResult()
{
double result=0;
result=numberA+numberB;
return result;
}
};
class OperationSub:public Operation
{
public:
double GetResult()
{
double result=0;
result=numberA-numberB;
return result;
}
};
class OperationMul:public Operation
{
public:
double GetResult()
{
double result=0;
result=numberA*numberB;
return result;
}
};
class OperationDiv:public Operation
{
public:
double GetResult()
{
double result=0;
if(numberB!=0)
result=numberA/numberB;
return result;
}
};
//抽象工厂类
class AbstractFactory
{
public:
virtual Operation* createOperation()
{
return new Operation;
}
};
//下面是四个具体工厂类,分别用于产生四个具体产品
class AddFactory:public AbstractFactory
{
public:
Operation* createOperation()
{
Operation* oper=new OperationAdd;
return oper;
}
};
class SubFactory:public AbstractFactory
{
public:
Operation* createOperation()
{
Operation* oper=new OperationSub;
return oper;
}
};
class MulFactory:public AbstractFactory
{
public:
Operation* createOperation()
{
Operation* oper=new OperationMul;
return oper;
}
};
class DivFactory:public AbstractFactory
{
public:
Operation* createOperation()
{
Operation* oper=new OperationDiv;
return oper;
}
};
//客户端
int main()
{ //客户端判断具体实例化那个子工厂,那个具体产品;
AbstractFactory* af=NULL;
af=new AddFactory();
Operation* oper=NULL;
oper=af->createOperation();
oper->setA(3);
oper->setB(2);
cout<<oper->GetResult()<<endl;
if(af!=NULL)
{
delete af;
af=NULL;
}
if(oper!=NULL)
{
delete oper;
oper=NULL;
}
system("pause");
return 0;
} 运行结果:
相关文章推荐
- jquery 常用的tabs效果代码
- Winform跨程序发送、接收消息
- EnumSet抽象类源码解析
- Codeforces Round #241 (Div. 2) B dp
- C语言 程序 位运算
- HTTP的请求方法OPTIONS
- Linux进程间通讯(IPC)------FIFO
- 动态规划——最长公共子序列问题(LCS)
- Centos6服务器部署JavaWeb项目(tomcat6+jdk6)
- Codeforces 696A. Lorenzo Von Matterhorn(map离散化)
- 建立ROS的代码环境
- 【Spring 2】spring的属性注入形式
- 源码分析-java-AbstractCollection
- jQuery之动画效果
- Java设计模式—中介者模式
- Fragment的setUserVisibleHint方法实现懒加载
- Android CrashHandler编写自己的异常捕获类
- css鼠标手型
- 2016.07.16【初中部 NOIP提高组 】模拟赛C
- hdu1048-密码问题 字符串转换