设计模式概述
设计模式是解决软件设计中常见问题的可复用方案,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。设计模式的目的是:
- 重用代码,提高开发效率
- 使代码更容易理解和维护
- 保证代码的可靠性和可扩展性
- 促进团队成员之间的沟通
设计模式分为三大类:创建型模式、结构型模式和行为型模式。
创建型模式
创建型模式关注对象的创建过程,提供了创建对象的最佳方式,隐藏了创建逻辑,使代码更加灵活。
1. 工厂模式(Factory Pattern)
定义:定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。
UML 类图:
- Product:抽象产品
- ConcreteProduct:具体产品
- Factory:抽象工厂
- ConcreteFactory:具体工厂
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| #include <iostream> #include <string>
class Shape { public: virtual void draw() = 0; virtual ~Shape() {} };
class Circle : public Shape { public: void draw() override { std::cout << "Drawing Circle" << std::endl; } };
class Rectangle : public Shape { public: void draw() override { std::cout << "Drawing Rectangle" << std::endl; } };
class ShapeFactory { public: virtual Shape* createShape() = 0; virtual ~ShapeFactory() {} };
class CircleFactory : public ShapeFactory { public: Shape* createShape() override { return new Circle(); } };
class RectangleFactory : public ShapeFactory { public: Shape* createShape() override { 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();
delete circle; delete rectangle; delete circleFactory; delete rectangleFactory;
return 0; }
|
适用场景:
- 当一个类不知道它所必须创建的对象的类时
- 当一个类希望由它的子类来指定它所创建的对象时
- 当类将创建对象的职责委托给多个帮助子类中的某一个,并且希望将哪一个帮助子类是代理者这一信息局部化时
2. 抽象工厂模式(Abstract Factory Pattern)
定义:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
UML 类图:
- AbstractFactory:抽象工厂
- ConcreteFactory:具体工厂
- AbstractProduct:抽象产品
- ConcreteProduct:具体产品
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
| #include <iostream> #include <string>
class AbstractProductA { public: virtual ~AbstractProductA() {} virtual std::string getName() = 0; };
class ProductA1 : public AbstractProductA { public: std::string getName() override { return "Product A1"; } };
class ProductA2 : public AbstractProductA { public: std::string getName() override { return "Product A2"; } };
class AbstractProductB { public: virtual ~AbstractProductB() {} virtual std::string getName() = 0; };
class ProductB1 : public AbstractProductB { public: std::string getName() override { return "Product B1"; } };
class ProductB2 : public AbstractProductB { public: std::string getName() override { return "Product B2"; } };
class AbstractFactory { public: virtual ~AbstractFactory() {} virtual AbstractProductA* createProductA() = 0; virtual AbstractProductB* createProductB() = 0; };
class ConcreteFactory1 : public AbstractFactory { public: AbstractProductA* createProductA() override { return new ProductA1(); }
AbstractProductB* createProductB() override { return new ProductB1(); } };
class ConcreteFactory2 : public AbstractFactory { public: AbstractProductA* createProductA() override { return new ProductA2(); }
AbstractProductB* createProductB() override { return new ProductB2(); } };
int main() { AbstractFactory* factory1 = new ConcreteFactory1(); AbstractProductA* productA1 = factory1->createProductA(); AbstractProductB* productB1 = factory1->createProductB();
std::cout << productA1->getName() << std::endl; std::cout << productB1->getName() << std::endl;
AbstractFactory* factory2 = new ConcreteFactory2(); AbstractProductA* productA2 = factory2->createProductA(); AbstractProductB* productB2 = factory2->createProductB();
std::cout << productA2->getName() << std::endl; std::cout << productB2->getName() << std::endl;
delete productA1; delete productB1; delete factory1; delete productA2; delete productB2; delete factory2;
return 0; }
|
适用场景:
- 当一个系统要独立于它的产品的创建、组合和表示时
- 当一个系统要由多个产品系列中的一个来配置时
- 当你要强调一系列相关的产品对象的设计以便进行联合使用时
3. 单例模式(Singleton Pattern)
定义:确保一个类只有一个实例,并提供一个全局访问点来访问这个唯一实例。
UML 类图:
代码示例(线程安全的懒汉式):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
| #include <iostream> #include <mutex>
class Singleton { private: Singleton() { std::cout << "Singleton 构造函数调用" << std::endl; }
~Singleton() { std::cout << "Singleton 析构函数调用" << std::endl; }
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
static Singleton* instance; static std::mutex mutex;
public: static Singleton* getInstance() { if (instance == nullptr) { std::lock_guard<std::mutex> lock(mutex); if (instance == nullptr) { instance = new Singleton(); } } return instance; }
static void destroyInstance() { std::lock_guard<std::mutex> lock(mutex); if (instance != nullptr) { delete instance; instance = nullptr; } }
void showMessage() { std::cout << "Hello Singleton!" << std::endl; } };
Singleton* Singleton::instance = nullptr; std::mutex Singleton::mutex;
int main() { Singleton* singleton1 = Singleton::getInstance(); Singleton* singleton2 = Singleton::getInstance();
std::cout << "singleton1 地址: " << singleton1 << std::endl; std::cout << "singleton2 地址: " << singleton2 << std::endl;
singleton1->showMessage();
Singleton::destroyInstance();
return 0; }
|
适用场景:
- 当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时
- 当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时
4. 建造者模式(Builder Pattern)
定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
UML 类图:
- Product:产品类
- Builder:抽象建造者
- ConcreteBuilder:具体建造者
- Director:指挥者
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
| #include <iostream> #include <string> #include <vector>
class Computer { private: std::vector<std::string> parts;
public: void addPart(const std::string& part) { parts.push_back(part); }
void show() { std::cout << "Computer Parts:" << std::endl; for (const auto& part : parts) { std::cout << "- " << part << std::endl; } } };
class ComputerBuilder { protected: Computer* computer;
public: ComputerBuilder() { computer = new Computer(); }
virtual ~ComputerBuilder() { delete computer; }
Computer* getComputer() { return computer; }
virtual void buildCPU() = 0; virtual void buildMemory() = 0; virtual void buildHardDrive() = 0; virtual void buildDisplay() = 0; };
class GamingComputerBuilder : public ComputerBuilder { public: void buildCPU() override { computer->addPart("Intel Core i9 CPU"); }
void buildMemory() override { computer->addPart("32GB DDR4 RAM"); }
void buildHardDrive() override { computer->addPart("2TB SSD"); }
void buildDisplay() override { computer->addPart("4K Gaming Monitor"); } };
class OfficeComputerBuilder : public ComputerBuilder { public: void buildCPU() override { computer->addPart("Intel Core i5 CPU"); }
void buildMemory() override { computer->addPart("16GB DDR4 RAM"); }
void buildHardDrive() override { computer->addPart("512GB SSD"); }
void buildDisplay() override { computer->addPart("24-inch Monitor"); } };
class Director { private: ComputerBuilder* builder;
public: Director(ComputerBuilder* builder) : builder(builder) {}
void setBuilder(ComputerBuilder* builder) { this->builder = builder; }
Computer* construct() { builder->buildCPU(); builder->buildMemory(); builder->buildHardDrive(); builder->buildDisplay(); return builder->getComputer(); } };
int main() { GamingComputerBuilder gamingBuilder; Director director(&gamingBuilder); Computer* gamingComputer = director.construct(); std::cout << "游戏电脑配置:" << std::endl; gamingComputer->show();
OfficeComputerBuilder officeBuilder; director.setBuilder(&officeBuilder); Computer* officeComputer = director.construct(); std::cout << "\n办公电脑配置:" << std::endl; officeComputer->show();
delete gamingComputer; delete officeComputer;
return 0; }
|
适用场景:
- 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时
- 当构造过程必须允许被构造的对象有不同的表示时
5. 原型模式(Prototype Pattern)
定义:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
UML 类图:
- Prototype:抽象原型类
- ConcretePrototype:具体原型类
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| #include <iostream> #include <string> #include <memory>
class Prototype { public: virtual ~Prototype() {} virtual std::unique_ptr<Prototype> clone() const = 0; virtual void show() const = 0; };
class ConcretePrototype : public Prototype { private: std::string name; int age;
public: ConcretePrototype(const std::string& name, int age) : name(name), age(age) {}
ConcretePrototype(const ConcretePrototype& other) : name(other.name), age(other.age) { std::cout << "ConcretePrototype 拷贝构造函数调用" << std::endl; }
std::unique_ptr<Prototype> clone() const override { return std::make_unique<ConcretePrototype>(*this); }
void show() const override { std::cout << "Name: " << name << ", Age: " << age << std::endl; }
void setName(const std::string& newName) { name = newName; }
void setAge(int newAge) { age = newAge; } };
int main() { std::unique_ptr<Prototype> prototype = std::make_unique<ConcretePrototype>("张三", 25);
std::unique_ptr<Prototype> clone1 = prototype->clone();
ConcretePrototype* concreteClone = dynamic_cast<ConcretePrototype*>(clone1.get()); if (concreteClone) { concreteClone->setName("李四"); concreteClone->setAge(30); }
std::unique_ptr<Prototype> clone2 = prototype->clone();
std::cout << "原型对象:" << std::endl; prototype->show();
std::cout << "\n克隆对象1:" << std::endl; clone1->show();
std::cout << "\n克隆对象2:" << std::endl; clone2->show();
return 0; }
|
适用场景:
- 当要实例化的类是在运行时指定时
- 当一个类的实例只能有几个不同状态组合中的一种时
- 当对象创建过程比较复杂,而复制一个已有对象比创建一个新对象更高效时
结构型模式
结构型模式关注类和对象的组合,通过继承或组合来组合类或对象,从而形成更大的结构。
1. 适配器模式(Adapter Pattern)
定义:将一个类的接口转换成客户端所期望的另一种接口,从而使原本接口不匹配而无法一起工作的两个类能够一起工作。
UML 类图:
- Target:目标接口
- Adaptee:适配者类
- Adapter:适配器类
代码示例(类适配器):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| #include <iostream> #include <string>
class Target { public: virtual ~Target() {} virtual void request() const { std::cout << "Target: Default request." << std::endl; } };
class Adaptee { public: void specificRequest() const { std::cout << "Adaptee: Specific request." << std::endl; } };
class Adapter : public Target, private Adaptee { public: void request() const override { std::cout << "Adapter: Translating request to Adaptee's interface." << std::endl; specificRequest(); } };
void clientCode(const Target* target) { target->request(); }
int main() { std::cout << "Client: Using Target directly." << std::endl; Target* target = new Target(); clientCode(target);
std::cout << "\nClient: Using Adaptee with Adapter." << std::endl; Adapter* adapter = new Adapter(); clientCode(adapter);
delete target; delete adapter;
return 0; }
|
适用场景:
- 当你想使用一个已经存在的类,但它的接口不符合你的需求时
- 当你想创建一个可复用的类,该类可以与其他不相关的类或不可预见的类(即接口可能不一定兼容的类)协同工作时
2. 桥接模式(Bridge Pattern)
定义:将抽象部分与它的实现部分分离,使它们都可以独立地变化。
UML 类图:
- Abstraction:抽象类
- RefinedAbstraction:扩充抽象类
- Implementor:实现接口
- ConcreteImplementor:具体实现类
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| #include <iostream> #include <string>
class Implementor { public: virtual ~Implementor() {} virtual void operationImpl() const = 0; };
class ConcreteImplementorA : public Implementor { public: void operationImpl() const override { std::cout << "ConcreteImplementorA operation" << std::endl; } };
class ConcreteImplementorB : public Implementor { public: void operationImpl() const override { std::cout << "ConcreteImplementorB operation" << std::endl; } };
class Abstraction { protected: Implementor* implementor;
public: Abstraction(Implementor* impl) : implementor(impl) {}
virtual ~Abstraction() {}
virtual void operation() const { implementor->operationImpl(); } };
class RefinedAbstraction : public Abstraction { public: RefinedAbstraction(Implementor* impl) : Abstraction(impl) {}
void operation() const override { std::cout << "RefinedAbstraction: " << std::endl; Abstraction::operation(); } };
int main() { Implementor* implA = new ConcreteImplementorA(); Abstraction* abstractionA = new RefinedAbstraction(implA); abstractionA->operation();
std::cout << "\n";
Implementor* implB = new ConcreteImplementorB(); Abstraction* abstractionB = new RefinedAbstraction(implB); abstractionB->operation();
delete implA; delete abstractionA; delete implB; delete abstractionB;
return 0; }
|
适用场景:
- 当一个类存在两个独立变化的维度,且这两个维度都需要进行扩展时
- 当你想避免在抽象和它的实现之间建立固定的绑定关系时
3. 装饰模式(Decorator Pattern)
定义:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式比生成子类更为灵活。
UML 类图:
- Component:抽象组件
- ConcreteComponent:具体组件
- Decorator:抽象装饰器
- ConcreteDecorator:具体装饰器
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
| #include <iostream> #include <string>
class Component { public: virtual ~Component() {} virtual std::string operation() const = 0; };
class ConcreteComponent : public Component { public: std::string operation() const override { return "ConcreteComponent"; } };
class Decorator : public Component { protected: Component* component;
public: Decorator(Component* comp) : component(comp) {}
~Decorator() { delete component; }
std::string operation() const override { return component->operation(); } };
class ConcreteDecoratorA : public Decorator { public: ConcreteDecoratorA(Component* comp) : Decorator(comp) {}
std::string operation() const override { return "ConcreteDecoratorA(" + Decorator::operation() + ")"; } };
class ConcreteDecoratorB : public Decorator { public: ConcreteDecoratorB(Component* comp) : Decorator(comp) {}
std::string operation() const override { return "ConcreteDecoratorB(" + Decorator::operation() + ")"; } };
void clientCode(Component* component) { std::cout << "Result: " << component->operation() << std::endl; }
int main() { Component* simple = new ConcreteComponent(); std::cout << "Client: I've got a simple component." << std::endl; clientCode(simple);
Component* decorator1 = new ConcreteDecoratorA(simple); std::cout << "\nClient: Now I've got a decorated component." << std::endl; clientCode(decorator1);
Component* decorator2 = new ConcreteDecoratorB(decorator1); std::cout << "\nClient: Now I've got a double decorated component." << std::endl; clientCode(decorator2);
delete decorator2;
return 0; }
|
适用场景:
- 当你需要给一个现有的类添加新的功能,但又不希望通过继承来实现时
- 当你需要动态地给一个对象添加功能,这些功能也可以动态地被撤销时
行为型模式
行为型模式关注对象之间的通信和职责分配,描述了对象之间如何协作以及如何分配职责。
1. 策略模式(Strategy Pattern)
定义:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。策略模式让算法独立于使用它的客户而变化。
UML 类图:
- Context:上下文类
- Strategy:策略接口
- ConcreteStrategy:具体策略类
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| #include <iostream> #include <string> #include <memory>
class Strategy { public: virtual ~Strategy() {} virtual std::string doOperation(const std::string& data) const = 0; };
class ConcreteStrategyA : public Strategy { public: std::string doOperation(const std::string& data) const override { std::string result = data; std::sort(result.begin(), result.end()); return result; } };
class ConcreteStrategyB : public Strategy { public: std::string doOperation(const std::string& data) const override { std::string result = data; std::reverse(result.begin(), result.end()); return result; } };
class Context { private: std::unique_ptr<Strategy> strategy;
public: Context(std::unique_ptr<Strategy> strat) : strategy(std::move(strat)) {}
void setStrategy(std::unique_ptr<Strategy> strat) { strategy = std::move(strat); }
std::string executeStrategy(const std::string& data) const { return strategy->doOperation(data); } };
int main() { std::string data = "abcdefg";
Context context(std::make_unique<ConcreteStrategyA>()); std::cout << "原始数据: " << data << std::endl; std::cout << "策略A结果: " << context.executeStrategy(data) << std::endl;
context.setStrategy(std::make_unique<ConcreteStrategyB>()); std::cout << "策略B结果: " << context.executeStrategy(data) << std::endl;
return 0; }
|
适用场景:
- 当你有许多相关的类,它们仅在行为上有所不同时
- 当你需要一个算法的不同变体时
- 当一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现时
2. 观察者模式(Observer Pattern)
定义:定义对象间的一种一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
UML 类图:
- Subject:主题类
- Observer:观察者接口
- ConcreteObserver:具体观察者类
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
| #include <iostream> #include <string> #include <vector> #include <memory>
class Subject;
class Observer { public: virtual ~Observer() {} virtual void update(const Subject& subject) = 0; };
class Subject { private: std::vector<Observer*> observers; int state;
public: Subject() : state(0) {}
void attach(Observer* observer) { observers.push_back(observer); }
void detach(Observer* observer) { auto it = std::find(observers.begin(), observers.end(), observer); if (it != observers.end()) { observers.erase(it); } }
void notify() { for (Observer* observer : observers) { observer->update(*this); } }
void setState(int newState) { if (state != newState) { state = newState; notify(); } }
int getState() const { return state; } };
class ConcreteObserver : public Observer { private: std::string name; int observerState;
public: ConcreteObserver(const std::string& name) : name(name), observerState(0) {}
void update(const Subject& subject) override { observerState = subject.getState(); std::cout << "观察者 " << name << " 状态更新为: " << observerState << std::endl; } };
int main() { Subject subject;
ConcreteObserver observer1("观察者1"); ConcreteObserver observer2("观察者2"); ConcreteObserver observer3("观察者3");
subject.attach(&observer1); subject.attach(&observer2); subject.attach(&observer3);
std::cout << "改变主题状态为 10" << std::endl; subject.setState(10);
std::cout << "\n移除观察者2" << std::endl; subject.detach(&observer2);
std::cout << "\n改变主题状态为 20" << std::endl; subject.setState(20);
return 0; }
|
适用场景:
- 当一个对象的改变需要同时改变其他对象时
- 当一个对象必须通知其他对象,而又不希望这些对象与它紧密耦合时
总结
设计模式是软件工程中的重要概念,掌握设计模式可以帮助开发者编写更加灵活、可维护和可扩展的代码。本文介绍了几种常用的设计模式,包括:
- 创建型模式:工厂模式、抽象工厂模式、单例模式、建造者模式、原型模式
- 结构型模式:适配器模式、桥接模式、装饰模式
- 行为型模式:策略模式、观察者模式
每种设计模式都有其特定的适用场景和优缺点,开发者应根据实际需求选择合适的设计模式。在实际开发中,往往需要结合多种设计模式来解决复杂的问题。