介绍
定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有相同的父类。因为在简单工厂模式中用于创建实例的方法是静态方法,因此简单工厂模式又被称为静态工厂方法模式,属于类创建型模式
实现
class Product {
public:void methodSame() { // 公共方法的实现std::cout << "methodSame" << std::endl;}virtual void methodDiff() = 0; // 抽象方法的声明,由具体产品实现
};class ConcreteProductA : public Product {
public:void methodDiff() override {std::cout << "ConcreteProductA" << std::endl;}
};class ConcreteProductB : public Product {
public:void methodDiff() override {std::cout << "ConcreteProductB" << std::endl;}
};class Factory {
public:static Product *getProduct(std::string arg) {Product *product = NULL;if (arg == "A") {product = new ConcreteProductA();} else if (arg == "B") {product = new ConcreteProductB();}return product;}
};int main() {Product *A = Factory::getProduct("A");A->methodSame();A->methodDiff();Product *B = Factory::getProduct("B");B->methodSame();B->methodDiff();return 0;
}
简单工厂模式的简化
将Factory合并到父类Product中,此时必须分别在头文件和源代码文件中分开编写,不然编译报错
class Product {
public:void methodSame();virtual void methodDiff() = 0; // 抽象方法的声明,由具体产品实现static Product *getProduct(std::string arg);
};class ConcreteProductA : public Product {
public:void methodDiff() override;
};class ConcreteProductB : public Product {
public:void methodDiff() override;
};
#include "myclass.h"void Product::methodSame() { // 公共方法的实现std::cout << "methodSame" << std::endl;
}Product* Product::getProduct(std::string arg) {Product *product = NULL;if (arg == "A") {product = new ConcreteProductA();} else if (arg == "B") {product = new ConcreteProductB();}return product;
}void ConcreteProductA::methodDiff() {std::cout << "ConcreteProductA" << std::endl;
}void ConcreteProductB::methodDiff() {std::cout << "ConcreteProductB" << std::endl;
}
总结
优点:
1. 工厂类包含必要的判断逻辑,可以决定什么时候创建哪一个产品类的实例。
2. 客户端无须知道所创建的具体产品类的类名,只需要知道对应的参数即可。
3. 通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。
缺点:
1. 由于工厂类集中了所有产品的创建逻辑,职责过重,一旦不能正常工作,整个系统都要受到影响。
2. 使用简单工厂模式势必会增加系统中类的个数(引入了新的工厂类),增加了系统的复杂度和理解难度。
3. 系统扩展困难。一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。
4. 简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构。
练习
使用简单工厂模式设计一个可以创建不同几何形状(如圆形、方形和三角形等)的绘图工具,每个几何图形都具有绘制draw()和擦除erase()两个方法,要求在绘制不支持的几何图形时,提示一个UnSupportedShapeException。
myclass.h
//
// Created by yuwp on 2024/1/12.
//#ifndef DESIGNPATTERNS_CLASS_H
#define DESIGNPATTERNS_MYCLASS_H#include <iostream>class Graphical {
public:virtual void draw() = 0;virtual void erase() = 0;static Graphical *getGraphical(std::string arg);
};class Circle : public Graphical {
public:void draw() override;void erase() override;
};class Square : public Graphical {
public:void draw() override;void erase() override;
};class Triangle : public Graphical {
public:void draw() override;void erase() override;
};class UnSupportedShapeException : public std::exception {
public:UnSupportedShapeException() {};~UnSupportedShapeException() {};const char* what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT override;
};#endif //DESIGNPATTERNS_CLASS_H
myclass.cpp
//
// Created by yuwp on 2024/1/12.
//#include "myclass.h"Graphical* Graphical::getGraphical(std::string arg) {if (arg == "circle") {return new Circle();} else if (arg == "square") {return new Square();} else if (arg == "triangle") {return new Triangle();} else {throw UnSupportedShapeException();}
}void Circle::draw() {std::cout << "Draw circle" << std::endl;
}void Circle::erase() {std::cout << "Erase circle" << std::endl;
}void Square::draw() {std::cout << "Draw square" << std::endl;
}void Square::erase() {std::cout << "Erase square" << std::endl;
}void Triangle::draw() {std::cout << "Draw triangle" << std::endl;
}void Triangle::erase() {std::cout << "Erase triangle" << std::endl;
}const char* UnSupportedShapeException::what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT {return "Unsupported shape";
}
main.cpp
#include <iostream>
#include <mutex>
#include "myclass.h"int main() {Graphical *graph;try {graph = Graphical::getGraphical("circle");graph->draw();graph->erase();graph = Graphical::getGraphical("square");graph->draw();graph->erase();graph = Graphical::getGraphical("triangle");graph->draw();graph->erase();graph = Graphical::getGraphical("unknown");graph->draw();graph->erase();} catch (const std::exception &e) {std::cout << e.what() << std::endl;}return 0;
}