前言
工厂模式是一种常见的创建型设计模式,它通过将对象的创建逻辑封装到一个类中,使得创建对象的过程与使用对象的过程分离,从而降低了代码的耦合性。在工厂模式中,我们定义一个工厂类来负责对象的创建,而客户端只需要向工厂类请求对象即可,不需要直接创建对象。
简单工厂模式 (Simple Factory Pattern):简单工厂模式中,只需要定义一个静态工厂方法,根据不同的参数返回不同的对象。这种方法通常适用于对象较少且创建过程相对简单的场景。
工厂方法模式 (Factory Method Pattern):工厂方法模式中,使用虚函数来定义工厂方法,让子类来实现工厂方法并创建对象。这种方法通常适用于需要创建多种类似对象的场景,例如创建不同类型的文件读写器、数据库连接器等。
抽象工厂模式 (Abstract Factory Pattern):抽象工厂模式中,使用抽象类或接口来定义工厂,让具体工厂类来实现工厂接口并创建对象。这种方法通常适用于需要创建一组相关或相互依赖的对象的场景,例如创建具有多种不同属性的GUI组件。
一.简单工厂模式
1.模式特点
1.适用场景——创建对象较少且创建过程相对简单的场景 ① 需要根据不同的条件来创建不同类型的对象,例如根据用户的输入创建不同类型的图形对象。② 创建对象的过程相对简单,不需要太多的初始化代码和复杂的构造函数。③ 产品类的创建逻辑不会频繁变化,不需要通过继承或实现接口来改变创建方法的行为。
2.优点 ① 简单易用:简单工厂模式使用静态方法创建对象,客户端代码只需要指定需要的对象类型即可,无需了解对象的创建细节。② 降低耦合:客户端代码只依赖工厂类,不依赖具体的产品类,从而降低了代码的耦合度。③ 可扩展性好:如果需要添加新的产品类,只需要在工厂类中添加相应的创建方法即可。
3.缺点 ① 可定制性不高:由于简单工厂模式使用静态方法创建对象,因此无法通过继承来改变创建方法的行为。② 开闭原则不完全遵守:当需要添加新的产品类时,必须修改工厂类的代码,不符合开闭原则中“对扩展开放,对修改关闭”的原则。
2.C++程序示例
# include <iostream>
# include <string>
using namespace std;
class Shape {
public :
virtual void draw ( ) = 0 ;
} ;
class Circle : public Shape {
public :
void draw ( ) {
cout << "Draw a circle" << endl;
}
} ;
class Rectangle : public Shape {
public :
void draw ( ) {
cout << "Draw a rectangle" << endl;
}
} ;
class Triangle : public Shape {
public :
void draw ( ) {
cout << "Draw a triangle" << endl;
}
} ;
class ShapeFactory {
public :
static Shape* createShape ( string type) {
if ( type == "circle" ) {
return new Circle ( ) ;
}
else if ( type == "rectangle" ) {
return new Rectangle ( ) ;
}
else if ( type == "triangle" ) {
return new Triangle ( ) ;
}
else {
return NULL ;
}
}
} ;
int main ( ) {
Shape* circle = ShapeFactory :: createShape ( "circle" ) ;
circle-> draw ( ) ;
Shape* rectangle = ShapeFactory :: createShape ( "rectangle" ) ;
rectangle-> draw ( ) ;
Shape* triangle = ShapeFactory :: createShape ( "triangle" ) ;
triangle-> draw ( ) ;
return 0 ;
}
在上面的示例中,定义了一个基类 Shape ,该类包含了一个纯虚函数 draw()。然后定义了三个派生类:Circle、Rectangle 和 Triangle ,分别表示圆形、矩形和三角形。 接下来定义了一个工厂类 ShapeFactory ,该类包含一个静态方法 createShape(),用于根据传入的参数来创建不同类型的对象。如果传入的参数不合法,则返回 NULL。 在 main() 函数中,通过调用 ShapeFactory::createShape() 方法来创建不同类型的对象,然后调用对象的 draw() 方法来绘制不同类型的图形。
二.工厂方法模式
1.模式特点
1.适用场景——需要创建多种类似对象的场景 ① 需要根据不同的条件来创建不同类型的对象,例如根据用户的输入创建不同类型的图形对象。② 产品类的创建逻辑相对复杂,需要一些初始化代码和复杂的构造函数。③ 产品类的创建逻辑可能发生变化,需要通过继承或实现接口来改变创建方法的行为。④ 需要将对象的创建过程与客户端代码分离,避免客户端代码与具体产品类耦合。
2.优点 ① 可扩展性好:当需要添加新的产品类时,只需要添加相应的工厂类,不需要修改已有的工厂类。② 开闭原则遵守:工厂方法模式中每个产品类对应一个工厂类,当需要添加新的产品类时,只需要添加相应的工厂类,不需要修改已有的工厂类,符合开闭原则。③ 易于维护:由于每个产品类对应一个工厂类,因此代码结构清晰,易于维护。
3.缺点 ① 类的数量增加:由于每个产品类都需要对应一个工厂类,因此类的数量增加,增加了系统的复杂度。② 代码量增加:由于需要定义多个工厂类,因此代码量增加。
2.C++程序示例
# include <iostream>
# include <string>
using namespace std;
class Shape {
public :
virtual void draw ( ) = 0 ;
} ;
class Circle : public Shape {
public :
void draw ( ) {
cout << "Draw a circle" << endl;
}
} ;
class Rectangle : public Shape {
public :
void draw ( ) {
cout << "Draw a rectangle" << endl;
}
} ;
class ShapeFactory {
public :
virtual Shape* createShape ( ) = 0 ;
} ;
class CircleFactory : public ShapeFactory {
public :
Shape* createShape ( ) {
return new Circle ( ) ;
}
} ;
class RectangleFactory : public ShapeFactory {
public :
Shape* createShape ( ) {
return new Rectangle ( ) ;
}
} ;
int main ( ) {
ShapeFactory* circleFactory = new CircleFactory ( ) ;
Shape* circle = circleFactory-> createShape ( ) ;
circle-> draw ( ) ;
ShapeFactory* rectangleFactory = new RectangleFactory ( ) ;
Shape* rectangle = rectangleFactory-> createShape ( ) ;
rectangle-> draw ( ) ;
return 0 ;
}
首先定义了一个基类Shape ,表示所有图形的共性,其中包含一个纯虚函数draw(),表示绘制该图形。然后定义了两个派生类Circle和Rectangle ,分别表示圆形和矩形。这两个派生类都实现了基类Shape中的draw()函数,具体实现是输出"Draw a circle"或"Draw a rectangle"。 接着定义了一个工厂基类ShapeFactory ,其中包含一个纯虚函数createShape(),用于创建具体的图形对象。 最后,定义了两个工厂派生类CircleFactory和RectangleFactory ,分别用于创建圆形和矩形。这两个派生类都实现了ShapeFactory中的createShape()函数,返回一个具体的圆形或矩形对象。 在主函数中,首先创建一个圆形工厂CircleFactory对象,然后通过调用其createShape()函数创建一个具体的圆形对象,并将其赋值给基类Shape指针circle。接着调用circle的draw()函数绘制圆形。 接下来,创建一个矩形工厂RectangleFactory对象,通过调用其createShape()函数创建一个具体的矩形对象,并将其赋值给基类Shape指针rectangle。接着调用rectangle的draw()函数绘制矩形。
三.抽象工厂模式
1.模式特点
1.适用场景——需要创建一组相关或相互依赖的对象的场景 ① 当系统需要一组相互关联或者相互依赖的对象,并且这些对象之间存在约束关系时,可以考虑使用抽象工厂模式。② 当系统需要支持多个产品族和产品等级结构,并且希望客户端能够动态选择所需要的对象时,可以考虑使用抽象工厂模式。② 当系统需要避免客户端和具体产品实现之间的耦合关系时,可以考虑使用抽象工厂模式。
2.优点 ① 封装性好:抽象工厂模式提供了一种良好的封装机制,使得对象的创建和实现分离,客户端只需要知道抽象工厂和抽象产品,而无需关心具体的实现。② 对象彼此约束:抽象工厂模式能够保证一组对象之间的约束关系,从而避免了客户端直接创建不兼容的对象。
3.缺点 ① 逻辑相对复杂:抽象工厂模式增加了系统的抽象性和理解难度,需要客户端理解抽象工厂和抽象产品,以及具体工厂和具体产品之间的关系。② 不易维护:抽象工厂模式的扩展性和可维护性较差,因为增加新的产品族和产品等级结构需要修改抽象工厂和所有具体工厂的代码。。
2.C++程序示例
# include <iostream>
# include <string>
using namespace std;
class AbstractProductA {
public :
virtual void use ( ) = 0 ;
} ;
class ProductA1 : public AbstractProductA {
public :
void use ( ) {
cout << "Using ProductA1" << endl;
}
} ;
class ProductA2 : public AbstractProductA {
public :
void use ( ) {
cout << "Using ProductA2" << endl;
}
} ;
class AbstractProductB {
public :
virtual void operate ( ) = 0 ;
} ;
class ProductB1 : public AbstractProductB {
public :
void operate ( ) {
cout << "Operating ProductB1" << endl;
}
} ;
class ProductB2 : public AbstractProductB {
public :
void operate ( ) {
cout << "Operating ProductB2" << endl;
}
} ;
class AbstractFactory {
public :
virtual AbstractProductA* createProductA ( ) = 0 ;
virtual AbstractProductB* createProductB ( ) = 0 ;
} ;
class Factory1 : public AbstractFactory {
public :
AbstractProductA* createProductA ( ) {
return new ProductA1 ( ) ;
}
AbstractProductB* createProductB ( ) {
return new ProductB1 ( ) ;
}
} ;
class Factory2 : public AbstractFactory {
public :
AbstractProductA* createProductA ( ) {
return new ProductA2 ( ) ;
}
AbstractProductB* createProductB ( ) {
return new ProductB2 ( ) ;
}
} ;
int main ( ) {
AbstractFactory* factory1 = new Factory1 ( ) ;
AbstractProductA* productA1 = factory1-> createProductA ( ) ;
AbstractProductB* productB1 = factory1-> createProductB ( ) ;
productA1-> use ( ) ;
productB1-> operate ( ) ;
AbstractFactory* factory2 = new Factory2 ( ) ;
AbstractProductA* productA2 = factory2-> createProductA ( ) ;
AbstractProductB* productB2 = factory2-> createProductB ( ) ;
productA2-> use ( ) ;
productB2-> operate ( ) ;
return 0 ;
}
这个程序实现了抽象工厂模式。它定义了抽象产品A和B接口,然后实现了具体的产品A1、A2、B1、B2。接着,定义了抽象工厂接口,它包含了创建产品A和B的纯虚函数。然后,实现了具体的工厂1和2,这两个工厂可以分别创建不同的产品组合。最后,在主函数中,先使用工厂1创建了产品A1和B1,再使用工厂2创建了产品A2和B2,并对它们进行了使用和操作。 抽象工厂模式的核心思想是将同一个产品族的产品集合起来进行统一创建,这样可以保证产品之间的兼容性。在实际应用中,抽象工厂模式常常用于创建不同操作系统或不同界面风格下的用户界面元素。此外,在需要支持多个产品组合的场景中,也可以考虑使用抽象工厂模式。