工厂模式
很多博客都有工厂模式相关的理论介绍,就不照本宣科了,直接从问题出发。看代码:
#pragma once
#include<cmath>
const double PI = acos(-1.0);
class IGraph {
public:
virtual double Area() = 0;//计算图形的面积
virtual ~IGraph() {};
};
class Square :public IGraph {//正方形
public:
Square(double Squarelen) :m_Squarelen(Squarelen) {}
double Area() override {
return m_Squarelen * m_Squarelen;
}
private:
double m_Squarelen;
};
class EqualTriangle :public IGraph {//等边三角形
public:
EqualTriangle(double Trilen) :m_Trilen(Trilen) {}
double Area() override {
return 0.5 * m_Trilen * m_Trilen * sin(60 * PI / 180);
}
private:
double m_Trilen;
};
class Circle :public IGraph {//圆
public:
Circle(double radius) :m_radius(radius) {}
double Area() override {
return m_radius * m_radius * PI;
}
private:
double m_radius;
};
1、定义一个图形抽象类,有一个计算图形面积的纯虚函数,有三个具体的图形继承它。该文件放在product.h头文件中。
class mainForm
{
public:
mainForm(double d):data(d){}
void Button_click()
{
IGraph* m_graph = new Circle(data);//依赖具体类
data = m_graph->Area();
cout << "show the area of graph:" << data << endl;
}
private:
double data;
};
2、实际中,假设有一个窗口,有一个按钮点击函Button_click(),作用是弹出图形面积。可以看到当要弹出不同图形不的面积时,都需要更改第7行的代码,依赖于具体类的实现,每次新的变化来临时,都需要更改mainForm的代码,违背了开放封闭原则。此时就引入了工厂模式。定义一个工厂类如下:
#pragma once
#include"product.h"
class IFactoty {
public:
virtual IGraph* CreateGraph(double data) = 0;//创建对象
virtual ~IFactoty() {}
};
class SquareFactory :public IFactoty{
public:
SquareFactory() {}
IGraph* CreateGraph(double data) override {
return new Square(data);
}
};
class EqualTriangleFactory :public IFactoty {
public:
EqualTriangleFactory() {}
IGraph* CreateGraph(double data) override {
return new EqualTriangle(data);
}
};
class CircleFactory :public IFactoty {
public:
CircleFactory() {}
IGraph* CreateGraph(double data) override {
return new Circle(data);
}
};
3、创建一个抽象工厂类,每个新增加的图形都作为一个具体的工厂类继承该类,实现CreateGraph方法。实现每次新增一个图形时,只需要增加一个产品类和对应的工厂类,无需修改mainForm类的代码,达到解耦的目的,此时mainForm代码如下:
class mainForm
{
public:
mainForm(IFactoty* factory, double d) {
this->factory = factory;
data = d;
}
void Button_click()
{
IGraph* m_graph = factory->CreateGraph(data);//无需再变更代码
data = m_graph->Area();
cout << "show the area of graph:" << data << endl;
}
private:
double data;
IFactoty* factory;
};
4、对应的测试代码如下:
int main()
{
IFactoty* factory1 = new CircleFactory();
mainForm* form1 = new mainForm(factory1,3);
form1->Button_click();
IFactoty* factory2 = new SquareFactory();
mainForm* form2 = new mainForm(factory2, 3);
form2->Button_click();
IFactoty* factory3 = new EqualTriangleFactory();
mainForm* form3 = new mainForm(factory3, 3);
form3->Button_click();
system("pause");
return 0;
}
5、测试结果如下图:
注意:
可以看到,在实例化产品类时,参数均为一个double类型的变量,这也是工厂模式的一个缺陷,即要求创建方法的参数(个数、类型、顺序)相同。例如,如果要创建一个长方形,给定长宽两个参数的话,就无法实现这个模式,需要考虑另外的处理方式。