一、概述
(1)创建型设计模式:只关注对象的创建机制,提供一种更灵活、更复杂的对象创建方式,而不是直接实例化对象。
1. 单例模式:确保类只有一个实例,并提供全局访问点。
2. 工厂方法模式:定义一个出创建对象的接口,但将对象的实际创建延迟到子类。
3. 抽象工厂模式:提供一个创建相关对象家族的接口,而无需指定具体类。
4. 建造者模式:将一个复杂对象的构建过程分解为多个步骤,以便更灵活的创建对象。
5. 原型模式:通过复制现有对象来创建新对象,而不是从头开始创建。
(2)结构性设计模式:关注如何组合类和对象以形成更大的结构,以解决系统中对象之间的关系。
1. 适配器模式:允许将一个接口转换为另一个客户端期望的接口。
2. 装饰者模式:动态地为对象添加新的功能,而无需修改其源代码。
3. 代理模式:提供一个代理对象以控制对其他对象的访问。
4. 组合模式:允许客户端以统一的方式处理单个对象和对象组合。
5. 桥接模式:将抽象部分与其实现分离,以便他们可以独立变化。
6. 外观设计模式:提供一个高级别的接口,将多个底层接口组合成一个更简单的接口,以供客户端使用。有助于隔离客户端代码和复杂子系统之间的耦合关系。
7. 享元模式:用于减少创建对象的数量,以减少内存占用和提高性能。
(3)行为型模式:关注对象之间的通信和职责分配,以帮助在系统中实现更松散耦合的对象之间的通信。
1. 策略模式:定义一系列算法,将他们封装成对象,并使其可以互相使用,以便根据需要动态选择算法。
2. 模板方法模式:定义一个算法的骨架,而将一些步骤的具体步骤延迟到子类中。允许在不改变算法结构的情况下,通过子类重写或扩展某些步骤来指定算法的行为。
3. 观察者模式:定义一种一对多的依赖关系,使得当一个对象状态发生变化时,所有依赖于它的对象都得到通知并自动更新。
4. 迭代器模式:
5. 责任链模式:将请求的发送者和接收者解耦,以便多个对象都有机会处理请求,将请求沿链传递,直到有一个对象处理它为止。
6. 命令模式:将请求封装成对象,以便可以参数化客户端对象,排队请求和记录日志,以及支持可撤销操作。
7. 备忘录模式:
8. 状态模式:允许对象在其内部状态发生变化时改变其行为。
9. 访问者模式:
10. 中介者模式:
11. 解释器模式:
二、单例模式
可以保证一个类只有一个实例;分为两种:饿汉式、懒汉式。
懒汉式:实例在第一次被请求时创建。有线程安全问题。
饿汉式:实例在类加载时就被创建,不管是否需要使用它,没有线程安全问题。
//有线程安全问题的懒汉式
class Singleton {
private:
static Singleton* instance;
Singleton() {} // 私有构造函数,禁止外部实例化
public:
static Singleton* getInstance() {
if (instance == nullptr) {
instance = new Singleton();
}
return instance;
}
};
//无线程安全问题的懒汉式:局部静态变量只有在第一次加载时才会初始化
class Singleton {
private:
Singleton() {} // 私有构造函数,禁止外部实例化
public:
static Singleton* getInstance() {
static Singleton* instance = new Singleton();
return instance;
}
};
//加双检锁解决线程安全的懒汉式
class Singleton {
private:
static Singleton* instance;
static std::mutex mtx; // 用于线程安全的锁
Singleton() {} // 私有构造函数,禁止外部实例化
public:
static Singleton* getInstance() {
// 第一次检查,如果实例已经存在,直接返回
if (instance == nullptr) {
std::lock_guard<std::mutex> lock(mtx); // 加锁
// 第二次检查,防止在等待锁期间其他线程已经创建实例
if (instance == nullptr) {
instance = new Singleton(); // 创建实例
}
}
return instance;
}
};
// 静态成员初始化
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mtx;
//饿汉式
class Singleton {
private:
static Singleton* instance;
Singleton() {} // 私有构造函数,禁止外部实例化
public:
static Singleton* getInstance() {
return instance;
}
};
Singleton* Singleton::instance = new Singleton;
懒汉式需要考虑多线程环境下的线程安全问题。可以使用加锁方式来确保线程安全,C++11后可以用局部静态变量来解决线程安全问题。饿汉式的优点是实现简单和线程安全,但可能存在内存浪费。
三、简单工厂模式
客户端只需要通过工厂类来创建所需的对象,而不需要直接实例化具体的对象,具体操作由工厂类内部实现。
// 产品类 - 图形
class Shape {
public:
virtual void draw() = 0;
};
// 具体产品类 - 圆形
class Circle : public Shape {
public:
void draw() override {
std::cout << "绘制圆形" << std::endl;
}
};
// 具体产品类 - 矩形
class Rectangle : public Shape {
public:
void draw() override {
std::cout << "绘制矩形" << std::endl;
}
};
// 工厂类
class ShapeFactory {
public:
// 根据类型创建图形对象
static Shape* createShape(std::string type) {
if (type == "Circle") {
return new Circle();
}
else if (type == "Rectangle") {
return new Rectangle();
}
else {
return nullptr; // 可以根据需要添加其他图形类型的创建逻辑
}
}
};
//使用
int main() {
Shape* shape1 = ShapeFactory::createShape("Circle");
Shape* shape2 = ShapeFactory::createShape("Rectangle");
shape1->draw();//绘制圆形
shape2->draw();//绘制矩形
}
优点:封装了对象的创建过程,客户端代码与具体类解耦,降低了代码的维护复杂度。
缺点:当需要添加新的产品类型时,需要修改工厂类的代码,违反了开闭原则(对扩展开放,对修改关闭)。
四、抽象工厂
创建一组相关的产品,而不是单个产品。
#include <iostream>
// 抽象产品接口
class Button {
public:
virtual void render() = 0;
};
// 具体产品类A
class WindowsButton : public Button {
public:
void render() override {
std::cout << "Rendering a Windows button." << std::endl;
}
};
// 具体产品类B
class MacButton : public Button {
public:
void render() override {
std::cout << "Rendering a Mac button." << std::endl;
}
};
// 抽象工厂接口
class GUIFactory {
public:
virtual Button* createButton() = 0;
};
// 具体工厂类A
class WindowsFactory : public GUIFactory {
public:
Button* createButton() override {
return new WindowsButton();
}
};
// 具体工厂类B
class MacFactory : public GUIFactory {
public:
Button* createButton() override {
return new MacButton();
}
};
int main() {
// 创建一个Windows风格的工厂
GUIFactory* windowsFactory = new WindowsFactory();
// 创建一个Windows风格的按钮
Button* windowsButton = windowsFactory->createButton();
// 渲染按钮
windowsButton->render(); // Output: Rendering a Windows button.
// 创建一个Mac风格的工厂
GUIFactory* macFactory = new MacFactory();
// 创建一个Mac风格的按钮
Button* macButton = macFactory->createButton();
// 渲染按钮
macButton->render(); // Output: Rendering a Mac button.
delete windowsFactory;
delete windowsButton;
delete macFactory;
delete macButton;
return 0;
}
可以实现一系列产品的一致性和互换性,同时也符合了开闭原则,是的系统更加灵活和可扩展。
五、建造者模式
将对象的构建过程与其表示分离,逐步构建复杂的对象。
#include <iostream>
#include <string>
// 产品类
class Pizza {
public:
void setDough(const std::string& dough) {
m_dough = dough;
}
void setSauce(const std::string& sauce) {
m_sauce = sauce;
}
void setTopping(const std::string& topping) {
m_topping = topping;
}
void showPizza() const {
std::cout << "Pizza with " << m_dough << " dough, " << m_sauce << " sauce, and " << m_topping << " topping." << std::endl;
}
private:
std::string m_dough;
std::string m_sauce;
std::string m_topping;
};
// 抽象建造者类
class PizzaBuilder {
public:
virtual ~PizzaBuilder() {}
virtual void buildDough() = 0;
virtual void buildSauce() = 0;
virtual void buildTopping() = 0;
virtual Pizza* getPizza() = 0;
};
// 具体建造者类A
class HawaiianPizzaBuilder : public PizzaBuilder {
public:
void buildDough() override {
m_pizza->setDough("cross");
}
void buildSauce() override {
m_pizza->setSauce("mild");
}
void buildTopping() override {
m_pizza->setTopping("ham and pineapple");
}
Pizza* getPizza() override {
return m_pizza;
}
private:
Pizza* m_pizza = new Pizza();
};
// 具体建造者类B
class SpicyPizzaBuilder : public PizzaBuilder {
public:
void buildDough() override {
m_pizza->setDough("pan baked");
}
void buildSauce() override {
m_pizza->setSauce("hot");
}
void buildTopping() override {
m_pizza->setTopping("pepperoni and jalapeno");
}
Pizza* getPizza() override {
return m_pizza;
}
private:
Pizza* m_pizza = new Pizza();
};
// 指导者类
class PizzaDirector {
public:
void setPizzaBuilder(PizzaBuilder* builder) {
m_builder = builder;
}
void constructPizza() {
m_builder->buildDough();
m_builder->buildSauce();
m_builder->buildTopping();
}
private:
PizzaBuilder* m_builder;
};
int main() {
PizzaDirector director;
HawaiianPizzaBuilder hawaiianBuilder;
director.setPizzaBuilder(&hawaiianBuilder);
director.constructPizza();
Pizza* hawaiianPizza = hawaiianBuilder.getPizza();
hawaiianPizza->showPizza();
SpicyPizzaBuilder spicyBuilder;
director.setPizzaBuilder(&spicyBuilder);
director.constructPizza();
Pizza* spicyPizza = spicyBuilder.getPizza();
spicyPizza->showPizza();
delete hawaiianPizza;
delete spicyPizza;
return 0;
}
优点:将对象的构建过程和表示分离,使得构建过程更加灵活,同时可以避免构造函数的参数过多的问题。
六、原型模式
通过复制已有的对象来创建新的对象,而无需重新构造对象。
#include <iostream>
#include <string>
// 图形基类
class Shape {
public:
virtual ~Shape() {}
virtual void draw() = 0;
virtual Shape* clone() = 0;
};
// 圆形类
class Circle : public Shape {
private:
std::string color;
int radius;
public:
Circle(std::string color, int radius) : color(color), radius(radius) {}
void draw() override {
std::cout << "Drawing a circle with color " << color << " and radius " << radius << std::endl;
}
Shape* clone() override {
return new Circle(*this);
}
};
int main() {
// 创建一个原型对象
Shape* circlePrototype = new Circle("red", 5);
// 克隆原型对象来创建新对象
Shape* circle1 = circlePrototype->clone();
Shape* circle2 = circlePrototype->clone();
// 绘制图形
circle1->draw(); // Output: Drawing a circle with color red and radius 5
circle2->draw(); // Output: Drawing a circle with color red and radius 5
delete circlePrototype;
delete circle1;
delete circle2;
return 0;
}
七、适配器模式
通过适配器可以将一个类的接口转换为另一个类的接口,是的两者可以无缝协同工作。
有三个角色:目标接口、适配器、被适配者
#include <iostream>
// 目标接口
class Target {
public:
virtual void request() = 0;
};
// 被适配者类
class Adaptee {
public:
void specificRequest() {
std::cout << "被适配者的特殊请求" << std::endl;
}
};
// 类适配器
class Adapter : public Target, private Adaptee {
public:
void request() override {
specificRequest();
}
};
int main() {
Target* adapter = new Adapter();
adapter->request();
delete adapter;
return 0;
}
八、装饰者模式
将对象包装在一个装饰者类中,然后逐层地添加装饰者,从而实现对对象的透明扩展。
#include <iostream>
// 抽象构件
class Component {
public:
virtual void operation() = 0;
};
// 具体构件
class ConcreteComponent : public Component {
public:
void operation() override {
std::cout << "执行具体构件的操作" << std::endl;
}
};
// 抽象装饰者
class Decorator : public Component {
protected:
Component* component;
public:
Decorator(Component* component) : component(component) {}
void operation() override {
if (component != nullptr) {
component->operation();
}
}
};
// 具体装饰者A
class ConcreteDecoratorA : public Decorator {
public:
ConcreteDecoratorA(Component* component) : Decorator(component) {}
void operation() override {
addedBehavior();
Decorator::operation();
}
void addedBehavior() {
std::cout << "具体装饰者A的附加操作" << std::endl;
}
};
// 具体装饰者B
class ConcreteDecoratorB : public Decorator {
public:
ConcreteDecoratorB(Component* component) : Decorator(component) {}
void operation() override {
addedBehavior();
Decorator::operation();
}
void addedBehavior() {
std::cout << "具体装饰者B的附加操作" << std::endl;
}
};
int main() {
Component* component = new ConcreteComponent();
Component* decoratorA = new ConcreteDecoratorA(component);
decoratorA->operation();
Component* decoratorB = new ConcreteDecoratorB(decoratorA);
decoratorB->operation();
delete decoratorB;
delete decoratorA;
delete component;
return 0;
}
九、代理模式
通过引入一个代理对象来替代原始对象,从而可以在不改变原始对象的情况下增加额外的功能或控制访问。
有三个角色:抽象主题、真实主题、代理
#include <iostream>
// 抽象主题
class Subject {
public:
virtual void request() = 0;
};
// 真实主题
class RealSubject : public Subject {
public:
void request() override {
std::cout << "真实主题的请求" << std::endl;
}
};
// 代理
class Proxy : public Subject {
private:
RealSubject* realSubject;
public:
Proxy() {
realSubject = new RealSubject();
}
~Proxy() {
delete realSubject;
}
void request() override {
// 在调用真实主题之前可以添加额外的逻辑
std::cout << "代理的请求" << std::endl;
// 委托给真实主题处理
realSubject->request();
}
};
int main() {
Subject* proxy = new Proxy();
proxy->request();
delete proxy;
return 0;
}
十、组合模式
有两种基本类型对象:叶子对象和组合对象。叶子对象表示树中的最细粒度的对象,没有子对象;组合对象是由一个或多个叶子对象或其他组合对象组成的对象,可以拥有子对象。
#include <iostream>
#include <vector>
// 抽象组件类
class Component {
public:
virtual void operation() = 0;
};
// 叶子组件类
class Leaf : public Component {
public:
void operation() override {
std::cout << "叶子组件的操作" << std::endl;
}
};
// 组合组件类
class Composite : public Component {
private:
std::vector<Component*> components;
public:
void addComponent(Component* component) {
components.push_back(component);
}
void operation() override {
std::cout << "组合组件的操作" << std::endl;
for (Component* component : components) {
component->operation();
}
}
};
int main() {
Component* leaf = new Leaf();
Component* composite = new Composite();
composite->addComponent(leaf);
composite->operation();
delete composite;
delete leaf;
return 0;
}
十一、桥接模式
十二、外观设计模式
允许客户端通过与外观对象交互,而不必直接与子系统的复杂性相互作用,降低客户端代码的复杂性和依赖性。
// 外观类 - 多媒体播放器
class MultimediaPlayer {
private:
AudioPlayer audioPlayer;
VideoPlayer videoPlayer;
SubtitlePlayer subtitlePlayer;
public:
MultimediaPlayer() {
// 初始化子系统
}
// 提供一个播放多媒体文件的简化接口
void playMedia(const std::string& mediaFilePath) {
audioPlayer.playAudio(mediaFilePath);
videoPlayer.playVideo(mediaFilePath);
subtitlePlayer.displaySubtitles(mediaFilePath);
}
};
// 子系统类 - 音频播放器
class AudioPlayer {
public:
void playAudio(const std::string& filePath) {
std::cout << "播放音频:" << filePath << std::endl;
// 实际音频播放逻辑
}
};
// 子系统类 - 视频播放器
class VideoPlayer {
public:
void playVideo(const std::string& filePath) {
std::cout << "播放视频:" << filePath << std::endl;
// 实际视频播放逻辑
}
};
// 子系统类 - 字幕显示器
class SubtitlePlayer {
public:
void displaySubtitles(const std::string& filePath) {
std::cout << "显示字幕:" << filePath << std::endl;
// 实际字幕显示逻辑
}
};
十三、享元模式
通过共享对象来最小化内存使用和提高性能。
#include <iostream>
#include <vector>
#include <unordered_map>
// 抽象享元类
class Flyweight {
public:
virtual void operation(int extrinsicState) = 0;
};
// 具体享元类
class ConcreteFlyweight : public Flyweight {
public:
void operation(int extrinsicState) override {
std::cout << "具体享元对象,外部状态为:" << extrinsicState << std::endl;
}
};
// 享元工厂类
class FlyweightFactory {
private:
std::unordered_map<int, Flyweight*> flyweights;
public:
Flyweight* getFlyweight(int key) {
if (flyweights.find(key) == flyweights.end()) {
flyweights[key] = new ConcreteFlyweight();
}
return flyweights[key];
}
};
int main() {
FlyweightFactory factory;
Flyweight* flyweight = factory.getFlyweight(1);
flyweight->operation(100);
flyweight = factory.getFlyweight(2);
flyweight->operation(200);
return 0;
}