当前位置: 首页 > news >正文

C++设计模式学习详解(23种)

C++设计模式学习详解

设计模式是软件开发中常见问题的可复用解决方案。它们不是可以直接转换为代码的成品,而是描述解决问题的通用方法。C++ 中常用的设计模式可以分为三大类:创建型模式、结构型模式和行为型模式。

一、创建型模式 (Creational Patterns)

创建型模式关注对象的创建过程,隐藏创建对象的细节,将客户端与对象的创建过程解耦。

1. 单例模式 (Singleton)

意图: 保证一个类只有一个实例,并提供一个全局访问点。

适用场景:

  • 需要确保某个类只有一个实例,例如数据库连接池、日志管理器等。
  • 需要全局访问某个类的实例。

实现: 将类的构造函数设为私有,提供一个静态方法获取实例。

代码示例:

class Singleton {
private:Singleton() {} // 私有构造函数static Singleton* instance; // 静态成员变量,指向唯一的实例
public:static Singleton* getInstance() { // 静态方法,获取实例if (instance == nullptr) {instance = new Singleton();}return instance;}// ...其他成员函数和变量...
};Singleton* Singleton::instance = nullptr; // 初始化静态成员变量int main() {Singleton* s1 = Singleton::getInstance();Singleton* s2 = Singleton::getInstance();// s1 和 s2 指向同一个实例return 0;
}

2. 工厂方法模式 (Factory Method)

意图: 定义一个创建对象的接口,但由子类决定实例化哪个类。工厂方法让类把实例化推迟到子类。

适用场景:

  • 当一个类不知道它所必须创建的对象的类的时候。
  • 当一个类希望由其子类来指定所创建的对象的时候。
  • 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。

实现: 定义一个抽象工厂类,具体工厂类继承抽象工厂类并实现创建具体产品的方法。

代码示例:

// 产品接口
class Product {
public:virtual void operation() = 0;
};// 具体产品
class ConcreteProductA : public Product {
public:void operation() override { std::cout << "ConcreteProductA operation" << std::endl; }
};class ConcreteProductB : public Product {
public:void operation() override { std::cout << "ConcreteProductB operation" << std::endl; }
};// 抽象工厂
class Creator {
public:virtual Product* factoryMethod() = 0;
};// 具体工厂
class ConcreteCreatorA : public Creator {
public:Product* factoryMethod() override { return new ConcreteProductA(); }
};class ConcreteCreatorB : public Creator {
public:Product* factoryMethod() override { return new ConcreteProductB(); }
};int main() {Creator* creatorA = new ConcreteCreatorA();Product* productA = creatorA->factoryMethod();productA->operation(); // 输出 "ConcreteProductA operation"Creator* creatorB = new ConcreteCreatorB();Product* productB = creatorB->factoryMethod();productB->operation(); // 输出 "ConcreteProductB operation"delete creatorA;delete productA;delete creatorB;delete productB;return 0;
}

3. 抽象工厂模式 (Abstract Factory)

意图: 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

适用场景:

  • 一个系统要独立于它的产品的创建、组合和表示时。
  • 一个系统要由多个产品系列中的一个来配置时。
  • 当你要强调一系列相关的产品对象的设计以便进行联合使用时。
  • 当你提供一个产品类库,而只想显示它们的接口而不是实现时。

实现: 定义一个抽象工厂接口,具体工厂类实现该接口并创建一系列相关产品。

代码示例:

// 抽象产品A
class AbstractProductA {
public:virtual void operationA() = 0;
};// 抽象产品B
class AbstractProductB {
public:virtual void operationB() = 0;
};// 具体产品A1
class ConcreteProductA1 : public AbstractProductA {
public:void operationA() override { std::cout << "ConcreteProductA1 operation" << std::endl; }
};// 具体产品A2
class ConcreteProductA2 : public AbstractProductA {
public:void operationA() override { std::cout << "ConcreteProductA2 operation" << std::endl; }
};// 具体产品B1
class ConcreteProductB1 : public AbstractProductB {
public:void operationB() override { std::cout << "ConcreteProductB1 operation" << std::endl; }
};// 具体产品B2
class ConcreteProductB2 : public AbstractProductB {
public:void operationB() override { std::cout << "ConcreteProductB2 operation" << std::endl; }
};// 抽象工厂
class AbstractFactory {
public:virtual AbstractProductA* createProductA() = 0;virtual AbstractProductB* createProductB() = 0;
};// 具体工厂1
class ConcreteFactory1 : public AbstractFactory {
public:AbstractProductA* createProductA() override { return new ConcreteProductA1(); }AbstractProductB* createProductB() override { return new ConcreteProductB1(); }
};// 具体工厂2
class ConcreteFactory2 : public AbstractFactory {
public:AbstractProductA* createProductA() override { return new ConcreteProductA2(); }AbstractProductB* createProductB() override { return new ConcreteProductB2(); }
};int main() {AbstractFactory* factory1 = new ConcreteFactory1();AbstractProductA* productA1 = factory1->createProductA();AbstractProductB* productB1 = factory1->createProductB();productA1->operationA(); // 输出 "ConcreteProductA1 operation"productB1->operationB(); // 输出 "ConcreteProductB1 operation"AbstractFactory* factory2 = new ConcreteFactory2();AbstractProductA* productA2 = factory2->createProductA();AbstractProductB* productB2 = factory2->createProductB();productA2->operationA(); // 输出 "ConcreteProductA2 operation"productB2->operationB(); // 输出 "ConcreteProductB2 operation"delete factory1;delete productA1;delete productB1;delete factory2;delete productA2;delete productB2;return 0;
}

区别:

  • 工厂方法模式:一个抽象产品,多个具体产品,一个抽象工厂,多个具体工厂,每个具体工厂生产一个具体产品。
  • 抽象工厂模式:多个抽象产品,多个具体产品,一个抽象工厂,多个具体工厂,每个具体工厂生产一系列相关的具体产品。

简单来说,工厂方法模式用于创建单个产品,而抽象工厂模式用于创建一系列相关产品。

4. 建造者模式 (Builder)

意图: 将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。

实现: 定义一个抽象建造者类,具体建造者类继承抽象建造者类并实现构建对象的各个部件。一个指挥者类负责指导建造者构建对象。

代码示例:

// 产品类
class Product {
public:void setPartA(const std::string& partA) { this->partA = partA; }void setPartB(const std::string& partB) { this->partB = partB; }// ... 其他部件
private:std::string partA;std::string partB;// ... 其他部件
};// 抽象建造者
class Builder {
public:virtual void buildPartA() = 0;virtual void buildPartB() = 0;// ... 其他构建部件方法virtual Product* getResult() = 0;
};// 具体建造者
class ConcreteBuilder : public Builder {
public:void buildPartA() override { product.setPartA("PartA"); }void buildPartB() override { product.setPartB("PartB"); }// ... 其他构建部件方法Product* getResult() override { return &product; }
private:Product product;
};// 指挥者
class Director {
public:void construct(Builder* builder) {builder->buildPartA();builder->buildPartB();// ... 其他构建步骤}
};

5. 原型模式 (Prototype)

意图: 使用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

实现: 定义一个原型接口,具体原型类实现该接口并实现克隆自身的方法。

代码示例:

// 原型接口
class Prototype {
public:virtual Prototype* clone() const = 0;
};// 具体原型
class ConcretePrototype1 : public Prototype {
public:Prototype* clone() const override { return new ConcretePrototype1(*this); }
};class ConcretePrototype2 : public Prototype {
public:Prototype* clone() const override { return new ConcretePrototype2(*this); }
};

二、结构型模式 (Structural Patterns)

结构型模式关注如何将类和对象组合成更大的结构,以简化结构和增加灵活性。

6. 适配器模式 (Adapter)

意图: 将一个类的接口转换成客户端所期望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

实现: 定义一个适配器类,该类持有被适配类的实例,并实现目标接口。

代码示例:

// 目标接口
class Target {
public:virtual void request() = 0;
};// 被适配类
class Adaptee {
public:void specificRequest() { /* ... */ }
};// 适配器类
class Adapter : public Target {
public:void request() override { adaptee.specificRequest(); }
private:Adaptee adaptee;
};

7. 桥接模式 (Bridge)

意图: 将抽象部分与它的实现部分分离,使它们都可以独立地变化。

实现: 定义一个抽象类和一个实现类接口,抽象类持有实现类接口的实例。

代码示例:

// 抽象部分
class Abstraction {
public:virtual void operation() = 0;
protected:Implementation* implementation;
};// 实现部分接口
class Implementation {
public:virtual void operationImpl() = 0;
};// 具体抽象
class RefinedAbstraction : public Abstraction {
public:void operation() override { implementation->operationImpl(); }
};// 具体实现
class ConcreteImplementationA : public Implementation {
public:void operationImpl() override { /* ... */ }
};class ConcreteImplementationB : public Implementation {
public:void operationImpl() override { /* ... */ }
};

8. 装饰器模式 (Decorator)

意图: 动态地给一个对象添加一些额外的职责。就扩展功能而言,它比生成子类方式更为灵活。

实现: 定义一个装饰器类,该类继承自被装饰类的基类,并持有被装饰类的实例。

代码示例:

// 组件接口
class Component {
public:virtual void operation() = 0;
};// 具体组件
class ConcreteComponent : public Component {
public:void operation() override { /* ... */ }
};// 装饰器基类
class Decorator : public Component {
public:Decorator(Component* component) : component(component) {}void operation() override { component->operation(); }
protected:Component* component;
};// 具体装饰器
class ConcreteDecoratorA : public Decorator {
public:ConcreteDecoratorA(Component* component) : Decorator(component) {}void operation() override {// 添加额外的职责Decorator::operation(); }
};

9. 组合模式 (Composite)

意图: 将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

实现: 定义一个组件接口,叶子节点和组合节点都实现该接口。组合节点持有组件接口的实例列表。

代码示例:

// 组件接口
class Component {
public:virtual void operation() = 0;virtual void add(Component* component) = 0;virtual void remove(Component* component) = 0;virtual Component* getChild(int index) = 0;
};// 叶子节点
class Leaf : public Component {
public:void operation() override { /* ... */ }void add(Component* component) override { /* ... */ }void remove(Component* component) override { /* ... */ }Component* getChild(int index) override { /* ... */ }
};// 组合节点
class Composite : public Component {
public:void operation() override { for (auto& child : children) {child->operation();}}void add(Component* component) override { children.push_back(component); }void remove(Component* component) override { /* ... */ }Component* getChild(int index) override { return children[index]; }
private:std::vector<Component*> children;
};

10. 外观模式 (Facade)

意图: 为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

实现: 定义一个外观类,该类持有子系统各个类的实例,并提供简化的接口。

代码示例:

// 子系统类
class SubsystemA {
public:void operationA() { /* ... */ }
};class SubsystemB {
public:void operationB() { /* ... */ }
};class SubsystemC {
public:void operationC() { /* ... */ }
};// 外观类
class Facade {
public:void operation() {subsystemA.operationA();subsystemB.operationB();subsystemC.operationC();}
private:SubsystemA subsystemA;SubsystemB subsystemB;SubsystemC subsystemC;
};

11. 享元模式 (Flyweight)

意图: 运用共享技术有效地支持大量细粒度的对象。

实现: 将对象的状态分为内部状态和外部状态,内部状态可以共享,外部状态由客户端提供。

代码示例:

// 享元接口
class Flyweight {
public:virtual void operation(const std::string& extrinsicState) = 0;
};// 具体享元
class ConcreteFlyweight : public Flyweight {
public:void operation(const std::string& extrinsicState) override {// 使用 intrinsicState 和 extrinsicState 进行操作}
private:std::string intrinsicState;
};// 享元工厂
class FlyweightFactory {
public:Flyweight* getFlyweight(const std::string& key) {if (flyweights.count(key)) {return flyweights[key];} else {Flyweight* flyweight = new ConcreteFlyweight();flyweights[key] = flyweight;return flyweight;}}
private:std::map<std::string, Flyweight*> flyweights;
};

12. 代理模式 (Proxy)

意图: 为其他对象提供一种代理以控制对这个对象的访问。

实现: 定义一个代理类,该类持有被代理对象的实例,并控制对被代理对象的访问。

代码示例:

// 主题接口
class Subject {
public:virtual void request() = 0;
};// 真实主题
class RealSubject : public Subject {
public:void request() override { /* ... */ }
};// 代理
class Proxy : public Subject {
public:void request() override {// 控制对 RealSubject 的访问realSubject.request();}
private:RealSubject realSubject;
};

三、行为型模式 (Behavioral Patterns)

行为型模式关注对象之间的交互和职责的分配。

13. 责任链模式 (Chain of Responsibility)

意图: 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

实现: 定义一个处理器接口,具体处理器类实现该接口并持有下一个处理器的实例。

代码示例:

// 处理器接口
class Handler {
public:virtual void handleRequest(int request) = 0;void setNextHandler(Handler* handler) { nextHandler = handler; }
protected:Handler* nextHandler;
};// 具体处理器
class ConcreteHandler1 : public Handler {
public:void handleRequest(int request) override {if (request < 10) {// 处理请求} else if (nextHandler != nullptr) {nextHandler->handleRequest(request);}}
};class ConcreteHandler2 : public Handler {
public:void handleRequest(int request) override {if (request >= 10 && request < 20) {// 处理请求} else if (nextHandler != nullptr) {nextHandler->handleRequest(request);}}
};

14. 命令模式 (Command)

意图: 将一个请求封装为一个对象,从而使你可用不同的请求对客户端进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。

实现: 定义一个命令接口,具体命令类实现该接口并持有接收者对象的实例。

代码示例:

// 命令接口
class Command {
public:virtual void execute() = 0;
};// 具体命令
class ConcreteCommand : public Command {
public:ConcreteCommand(Receiver* receiver) : receiver(receiver) {}void execute() override { receiver->action(); }
private:Receiver* receiver;
};// 接收者
class Receiver {
public:void action() { /* ... */ }
};

15. 解释器模式 (Interpreter)

意图: 给定一个语言, 定义它的文法的一种表示,并定义一个解释器, 该解释器使用该表示来解释语言中的句子。

实现: 定义一个抽象表达式接口,具体表达式类实现该接口并解释对应的语法规则。

代码示例:

// 抽象表达式
class Expression {
public:virtual int interpret() = 0;
};// 终结符表达式
class Number : public Expression {
public:Number(int number) : number(number) {}int interpret() override { return number; }
private:int number;
};// 非终结符表达式
class Add : public Expression {
public:Add(Expression* left, Expression* right) : left(left), right(right) {}int interpret() override { return left->interpret() + right->interpret(); }
private:Expression* left;Expression* right;
};

16. 迭代器模式 (Iterator)

意图: 提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。

实现: 定义一个迭代器接口,具体迭代器类实现该接口并持有聚合对象的实例。

代码示例:

// 聚合接口
class Aggregate {
public:virtual Iterator* createIterator() = 0;
};// 迭代器接口
class Iterator {
public:virtual bool hasNext() = 0;virtual int next() = 0;
};// 具体聚合
class ConcreteAggregate : public Aggregate {
public:Iterator* createIterator() override { return new ConcreteIterator(this); }int getItem(int index) { return items[index]; }int getSize() { return items.size(); }
private:std::vector<int> items;
};// 具体迭代器
class ConcreteIterator : public Iterator {
public:ConcreteIterator(ConcreteAggregate* aggregate) : aggregate(aggregate), index(0) {}bool hasNext() override { return index < aggregate->getSize(); }int next() override { return aggregate->getItem(index++); }
private:ConcreteAggregate* aggregate;int index;
};

17. 中介者模式 (Mediator)

意图: 用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

实现: 定义一个中介者接口,具体中介者类实现该接口并持有各个同事对象的实例。

代码示例:

// 中介者接口
class Mediator {
public:virtual void notify(Colleague* colleague, std::string event) = 0;
};// 同事接口
class Colleague {
public:Colleague(Mediator* mediator) : mediator(mediator) {}
protected:Mediator* mediator;
};// 具体中介者
class ConcreteMediator : public Mediator {
public:void notify(Colleague* colleague, std::string event) override {if (event == "A") {colleagueB->doB();} else if (event == "B") {colleagueA->doA();}}void setColleagueA(Colleague* colleague) { colleagueA = colleague; }void setColleagueB(Colleague* colleague) { colleagueB = colleague; }
private:Colleague* colleagueA;Colleague* colleagueB;
};// 具体同事
class ConcreteColleagueA : public Colleague {
public:ConcreteColleagueA(Mediator* mediator) : Colleague(mediator) {}void doA() { /* ... */ }
};class ConcreteColleagueB : public Colleague {
public:ConcreteColleagueB(Mediator* mediator) : Colleague(mediator) {}void doB() { /* ... */ }
};

18. 备忘录模式 (Memento)

意图: 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。

实现: 定义一个备忘录类,用于存储对象的内部状态。发起人对象可以创建备忘录对象并恢复状态。

代码示例:

// 发起人
class Originator {
public:void setState(const std::string& state) { this->state = state; }std::string getState() { return state; }Memento* createMemento() { return new Memento(state); }void setMemento(Memento* memento) { state = memento->getState(); }
private:std::string state;
};// 备忘录
class Memento {
public:Memento(const std::string& state) : state(state) {}std::string getState() { return state; }
private:std::string state;
};

19. 观察者模式 (Observer)

意图: 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。

实现: 定义一个主题接口和一个观察者接口,主题类持有观察者列表,并在状态改变时通知观察者。

代码示例:

// 主题接口
class Subject {
public:virtual void registerObserver(Observer* observer) = 0;virtual void removeObserver(Observer* observer) = 0;virtual void notifyObservers() = 0;
};// 观察者接口
class Observer {
public:virtual void update(Subject* subject) = 0;
};// 具体主题
class ConcreteSubject : public Subject {
public:void registerObserver(Observer* observer) override { observers.push_back(observer); }void removeObserver(Observer* observer) override { /* ... */ }void notifyObservers() override {for (auto& observer : observers) {observer->update(this);}}void setState(int state) { this->state = state; notifyObservers(); }int getState() { return state; }
private:std::vector<Observer*> observers;int state;
};// 具体观察者
class ConcreteObserver : public Observer {
public:void update(Subject* subject) override {// 获取主题的状态更新ConcreteSubject* concreteSubject = dynamic_cast<ConcreteSubject*>(subject);int state = concreteSubject->getState();// ... 处理状态更新}
};

20. 状态模式 (State)

意图: 允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。

实现: 定义一个状态接口,具体状态类实现该接口并持有上下文对象的实例。上下文对象持有当前状态对象的实例。

代码示例:

// 状态接口
class State {
public:virtual void handle(Context* context) = 0;
};// 上下文
class Context {
public:void setState(State* state) { this->state = state; }void request() { state->handle(this); }
private:State* state;
};// 具体状态
class ConcreteStateA : public State {
public:void handle(Context* context) override {// 处理请求并可能改变上下文的状态context->setState(new ConcreteStateB()); }
};class ConcreteStateB : public State {
public:void handle(Context* context) override {// 处理请求并可能改变上下文的状态}
};

21. 策略模式 (Strategy)

意图: 定义一系列的算法,把它们一个个封装起来, 并且使它们可互相替换。本模式使得算法可独立于使用它的客户而变化。

实现: 定义一个策略接口,具体策略类实现该接口。上下文对象持有策略对象的实例。

代码示例:

// 策略接口
class Strategy {
public:virtual void algorithmInterface() = 0;
};// 具体策略
class ConcreteStrategyA : public Strategy {
public:void algorithmInterface() override { /* ... */ }
};class ConcreteStrategyB : public Strategy {
public:void algorithmInterface() override { /* ... */ }
};// 上下文
class Context {
public:void setStrategy(Strategy* strategy) { this->strategy = strategy; }void contextInterface() { strategy->algorithmInterface(); }
private:Strategy* strategy;
};

22. 模板方法模式 (Template Method)

意图: 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

实现: 定义一个抽象类,该类包含一个模板方法和一些基本操作。具体子类可以重定义基本操作,但不能修改模板方法。

代码示例:

// 抽象类
class AbstractClass {
public:void templateMethod() {operation1();operation2();}
protected:virtual void operation1() = 0;virtual void operation2() = 0;
};// 具体子类
class ConcreteClass : public AbstractClass {
protected:void operation1() override { /* ... */ }void operation2() override { /* ... */ }
};

23. 访问者模式 (Visitor)

意图: 表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

实现: 定义一个访问者接口,具体访问者类实现该接口并对不同类型的元素执行不同的操作。元素类提供一个接受访问者的方法。

代码示例:

// 元素接口
class Element {
public:virtual void accept(Visitor* visitor) = 0;
};// 访问者接口
class Visitor {
public:virtual void visitConcreteElementA(ConcreteElementA* element) = 0;virtual void visitConcreteElementB(ConcreteElementB* element) = 0;
};// 具体元素
class ConcreteElementA : public Element {
public:void accept(Visitor* visitor) override { visitor->visitConcreteElementA(this); }
};class ConcreteElementB : public Element {
public:void accept(Visitor* visitor) override { visitor->visitConcreteElementB(this); }
};// 具体访问者
class ConcreteVisitor1 : public Visitor {
public:void visitConcreteElementA(ConcreteElementA* element) override { /* ... */ }void visitConcreteElementB(ConcreteElementB* element) override { /* ... */ }
};class ConcreteVisitor2 : public Visitor {
public:void visitConcreteElementA(ConcreteElementA* element) override { /* ... */ }void visitConcreteElementB(ConcreteElementB* element) override { /* ... */ }
};

C++设计模式区别及应用

设计模式之间最大的区别在于它们解决的问题和应用场景不同。创建型模式关注对象的创建,结构型模式关注对象的组合,行为型模式关注对象之间的交互。

选择合适的设计模式需要根据具体问题进行分析,没有一种模式适用于所有情况。

模式分类意图应用场景区别
单例模式 (Singleton)创建型保证一个类只有一个实例,并提供一个全局访问点。数据库连接池、日志记录器、配置文件读取器与其他创建型模式不同,它只关注单个实例的创建和访问。
工厂方法模式 (Factory Method)创建型定义一个创建对象的接口,但由子类决定实例化哪个类。当一个类无法预料要创建哪种对象,或需要将对象的创建委托给子类时。与抽象工厂模式相比,它只关注单个产品的创建,而不是一系列相关产品。
抽象工厂模式 (Abstract Factory)创建型提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。当需要创建一系列相关产品,且希望隐藏具体产品的创建细节时。与工厂方法模式相比,它关注一系列相关产品的创建。
建造者模式 (Builder)创建型将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。当一个对象的创建过程较为复杂,包含多个步骤,且希望将构建过程与表示分离时。与工厂模式相比,它更注重构建过程的灵活性,可以逐步构建对象。
原型模式 (Prototype)创建型用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。当创建对象的成本较高,或希望避免重复创建相同对象时。与其他创建型模式不同,它通过拷贝原型对象来创建新对象。
适配器模式 (Adapter)结构型将一个类的接口转换成客户端所期望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。当需要使用一个已存在的类,但其接口与当前系统的接口不兼容时。与桥接模式相比,它更注重接口的转换,而不是抽象与实现的分离。
桥接模式 (Bridge)结构型将抽象部分与它的实现部分分离,使它们都可以独立地变化。当需要将抽象与实现分离,使其可以独立变化时。与适配器模式相比,它更注重抽象与实现的分离,而不是接口的转换。
组合模式 (Composite)结构型将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。当需要表示对象的层次结构,且希望用户能够以相同的方式处理单个对象和组合对象时。与装饰器模式相比,它更注重对象的组合,而不是动态地添加功能。
装饰器模式 (Decorator)结构型动态地给一个对象添加一些额外的职责。就扩展功能而言,它比生成子类方式更为灵活。当需要动态地给一个对象添加功能,且不希望通过继承来实现时。与组合模式相比,它更注重动态地添加功能,而不是对象的组合。
外观模式 (Facade)结构型为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。当需要简化一个复杂子系统的使用,或隐藏子系统的内部细节时。与适配器模式相比,它更注重简化接口,而不是转换接口。
享元模式 (Flyweight)结构型运用共享技术有效地支持大量细粒度的对象。当需要创建大量细粒度的对象,且这些对象大部分属性相同,只有少量属性不同时。与其他结构型模式不同,它更注重对象的共享,以节省内存和提高性能。
代理模式 (Proxy)结构型为其他对象提供一种代理以控制对这个对象的访问。当需要控制对一个对象的访问,或延迟对象的创建时。与适配器模式相比,它更注重控制对象的访问,而不是转换接口。
责任链模式 (Chain of Responsibility)行为型为解除请求的发送者和接收者之间耦合,而使多个对象都有机会处理这个请求。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。当需要将请求的处理者与发送者解耦,或希望多个对象都有机会处理请求时。与命令模式相比,它更注重请求的传递,而不是请求的封装。
命令模式 (Command)行为型将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。当需要将请求封装成对象,以便参数化、排队、记录日志或支持撤销操作时。与责任链模式相比,它更注重请求的封装,而不是请求的传递。
解释器模式 (Interpreter)行为型给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。当需要解释一种简单的语言,或希望将语言的解释与应用逻辑分离时。与其他行为型模式不同,它更注重语言的解释。
迭代器模式 (Iterator)行为型提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。当需要顺序访问一个聚合对象中的元素,且不希望暴露该对象的内部表示时。与其他行为型模式不同,它更注重对聚合对象的遍历。
中介者模式 (Mediator)行为型用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。当多个对象之间存在复杂的交互关系,且希望降低对象之间的耦合度时。与观察者模式相比,它更注重对象之间的交互,而不是事件的通知。
备忘录模式 (Memento)行为型在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。当需要保存一个对象的内部状态,以便以后恢复时。与其他行为型模式不同,它更注重对象的内部状态的保存和恢复。
观察者模式 (Observer)行为型定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。当一个对象的状态发生改变时,需要通知其他依赖于它的对象时。与中介者模式相比,它更注重事件的通知,而不是对象之间的交互。
状态模式 (State)行为型允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。当一个对象的行為取决于其内部状态,且需要在状态改变时改变其行为时。与策略模式相比,它更注重状态的改变,而不是算法的选择。
策略模式 (Strategy)行为型定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。当需要在运行时选择不同的算法,或希望将算法的实现与使用分离时。与状态模式相比,它更注重算法的选择,而不是状态的改变。
模板方法模式 (Template Method)行为型定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。当需要定义一个算法的骨架,并将一些步骤延迟到子类中实现时。与策略模式相比,它更注重算法结构的定义,而不是算法的具体实现。
访问者模式 (Visitor)行为型表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。当需要对一个对象结构中的元素执行不同的操作,且不希望修改元素的类时。与其他行为型模式不同,它更注重对对象结构的访问和操作。

注意:

  • 以上表格只是对 23 种设计模式的简要概括,每种模式都有其自身的特点和适用场景,需要根据具体情况选择合适的模式。
  • 在实际应用中,可以组合使用多种设计模式来解决复杂的问题。

相关文章:

C++设计模式学习详解(23种)

C设计模式学习详解 设计模式是软件开发中常见问题的可复用解决方案。它们不是可以直接转换为代码的成品&#xff0c;而是描述解决问题的通用方法。C 中常用的设计模式可以分为三大类&#xff1a;创建型模式、结构型模式和行为型模式。 一、创建型模式 (Creational Patterns) …...

Matlab中实现类属性仅在首次创建类实例时初始化

背景描述: 在自定义类中&#xff0c;需要定义一些属性(标志位)用于触发某些方法&#xff0c;标志位只需要在类对象第一次实例化时赋初值&#xff0c;之后的值需要在特定的地方设置。怎样保证在不同实例中&#xff0c;标志位的值仅在特定的时候改变&#xff0c;其他时候保持不变…...

FLINK SQL动态表连续查询

SQL动态表 在Apache Flink中&#xff0c;动态表是Flink SQL处理流数据的核心概念之一。与静态表&#xff08;如关系数据库中的传统表&#xff09;不同&#xff0c;动态表的内容是随时间不断变化的&#xff0c;因为它们能够反映数据流的最新状态。动态表可以看作是对数据流的一…...

C++ | Leetcode C++题解之第468题验证IP地址

题目&#xff1a; 题解&#xff1a; class Solution { public:string validIPAddress(string queryIP) {if (queryIP.find(.) ! string::npos) {// IPv4int last -1;for (int i 0; i < 4; i) {int cur (i 3 ? queryIP.size() : queryIP.find(., last 1));if (cur st…...

每日学习一个数据结构-图

文章目录 图基础一、图的定义二、图的相关概念三、图的分类四、图的使用场景 和图相关的算法一、图的遍历算法二、最短路径算法三、最小生成树算法四、图匹配算法五、网络流算法 图基础 一、图的定义 在数学中&#xff0c;图是描述于一组对象的结构&#xff0c;其中某些对象对…...

kali(专业的渗透测试虚拟机)|kali下载链接地址 |kali安装 |kali部署指南

介绍 kali 是Debian开源linux系统体系下的子分支之一 Debian-kali 扩展&#xff1a;Ubuntu也是Debian开源linux系统体系下的子分支之一 Debian-ubuntu 安装kali 2023.03 稳定版 Index of /kali-images/kali-2023.1/ 安装可以参考他的教程&#xff0c; 写的很详细了…...

中国地级市生态韧性数据及城市生态韧性数据(2000-2022年)

一测算方式&#xff1a; 参考C刊《管理学刊》楚尔鸣&#xff08;2023&#xff09;老师的做法&#xff0c;城市生态韧性主要衡量一个城市在面临生态环境系统压力或突发冲击时&#xff0c;约束污染排放、维护生态环境状态和治理能力提升的综合水平。 参考郭海红和刘新民的研究&a…...

应对网络安全挑战:App等保测评的重要性与策略

在全球数字化转型的大潮中&#xff0c;移动应用(App)作为连接人们日常生活与互联网世界的桥梁&#xff0c;其数量与日俱增&#xff0c;功能日趋多样化。与此同时&#xff0c;App背后潜藏的网络安全风险也随之上升&#xff0c;数据泄露、隐私侵犯、恶意软件植入等问题频发&#…...

vue后台管理系统从0到1搭建(4)各组件的搭建

文章目录 vue后台管理系统从0到1搭建&#xff08;4&#xff09;各组件的搭建Main.vue 组件的初构 vue后台管理系统从0到1搭建&#xff08;4&#xff09;各组件的搭建 Main.vue 组件的初构 根据我们的效果来看&#xff0c;分析一下&#xff0c;我们把左边的区域分为一个组件&am…...

LabVIEW开关磁阻电机特性测量系统

基于LabVIEW软件和特定硬件组件的开关磁阻电机&#xff08;SRM&#xff09;特性测量系统&#xff0c;结合多功能数据采集卡&#xff0c;统能够准确地测量并分析SRM的电磁特性&#xff0c;从而支持电机模型的精确建立和性能优化。 项目背景 在工业生产和家用电器领域&#xff0…...

在当前网络环境中查看所有IPv4与Mac地址的方法

在powershell界面中&#xff1a; # 获取并显示所有网络接口的MAC地址和IPv4地址 Get-NetAdapter | Select-Object -Property Name, MacAddress, Status Get-NetAdapter | Get-NetIPAddress -AddressFamily IPv4 | Select-Object -Property InterfaceAlias, IPAddress, PrefixL…...

CSS @规则(At-rules)系列详解___@charset规则使用方法

CSS 规则(At-rules)系列详解 ___charset规则使用方法 本篇目录&#xff1a; 零、时光宝盒 一、charset规则定义和用法 二、CSS charset语法 三、charset 使用方法例子 1、正确使用方法 2、无效的&#xff0c;错误的使用方法 零、时光宝盒 &#xff08;https://blog.csd…...

黑马程序员C++核心编程学习笔记

黑马程序员C核心编程学习笔记 一、内存 1.1 内存四区 C程序在执行时&#xff0c;将内存大致分为4个区域&#xff1a;代码区&#xff0c;全局区&#xff0c;栈区&#xff0c;堆区 代码区&#xff1a;存放函数体的的二进制代码&#xff0c;操作系统管理。 &#x1f535;特点&a…...

六自由度平台

力姆泰克六自由度平台 安装方便&#xff0c;维护简单 多重机械电气安全保护 向下翻动查看更多 力姆泰克伺服系统集成 全新革命性结构设计与六轴先进伺服控制原理的结合&#xff0c;力姆泰克公司引进国外的专业技术在国内全新推出 全电动六自由度平台。将完全替代市场上原有的…...

【Node.js 下载及npm安装配置】亲测可用

Node.js 下载及npm安装配置 安装nodejs设置安装angular 安装nodejs 下载适用自己系统的node.js&#xff0c;官网&#xff1a;https://nodejs.cn/download/。默认安装即可。查看是否安装成功&#xff0c;node -v&#xff0c;npm -v &#xff0c;出现版本号即安装成功。 设置 …...

Qt C++设计模式->访问者模式

访问者模式&#xff08;Visitor Pattern&#xff09;是一种行为型设计模式&#xff0c;它将操作与对象结构分离&#xff0c;使得你可以在不改变对象结构的前提下定义作用于这些对象的新操作。访问者模式通过引入一个访问者对象&#xff0c;允许你在不修改类的前提下向已有类添加…...

手机在网状态的详细应用场景有哪些?

手机在网状态的详细应用场景涵盖了多个行业和领域&#xff0c;以下是一些具体的例子&#xff1a; 金融行业 风控审核&#xff1a;银行、贷款公司等金融机构在审批贷款或信用卡时&#xff0c;可以通过查询手机在网状态来验证申请人的手机号码是否真实有效&#xff0c;从而降低欺…...

Linux的kafka安装部署

1.kafka是一个分布式的,去中心化的,高吞吐低延迟,订阅模式的消息队列系统 确保要有jdk与zookeeper安装配置 2.下载kafka安装包 http://archive.apache.org/dist/kafka/2.4.1/kafka_2.12-2.4.1.tgz 此时可以wget http://archive.apache.org/dist/kafka/2.4.1/kafka_2.12-2.4.…...

docker部署虚拟机

创建新的容器web02&#xff0c;-v表示目录映射&#xff0c;-p时端口映射&#xff0c;把宿主机目录挂载到容器中 docker run -itd -p 80:80 -v /data/webapps/www/:/usr/share/nginx/html/ --nameweb02 nginx:latest 此时我们在发布网站时只需要放在宿主机的目录里就可以了 解…...

如何用ChatGPT 8小时写出一篇完整论文(附完整提示词)

今天教大家如何利用ChatGPT完成一篇完整的论文。只需要一个标题&#xff0c;剩下全部由ChatGPT完成。总耗时8小时。 阅前提醒&#xff1a; 1.适用人群&#xff1a;这个方法适合应付简单的学术任务&#xff0c;比如日常小论文或投稿一般期刊。但如果你要写高水平的论文&#xf…...

脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)

一、数据处理与分析实战 &#xff08;一&#xff09;实时滤波与参数调整 基础滤波操作 60Hz 工频滤波&#xff1a;勾选界面右侧 “60Hz” 复选框&#xff0c;可有效抑制电网干扰&#xff08;适用于北美地区&#xff0c;欧洲用户可调整为 50Hz&#xff09;。 平滑处理&…...

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…...

pam_env.so模块配置解析

在PAM&#xff08;Pluggable Authentication Modules&#xff09;配置中&#xff0c; /etc/pam.d/su 文件相关配置含义如下&#xff1a; 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块&#xff0c;负责验证用户身份&am…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统

目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索&#xff08;基于物理空间 广播范围&#xff09;2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列&#xff0c;以便知晓哪些列包含有价值的数据&#xff0c;…...

LeetCode - 199. 二叉树的右视图

题目 199. 二叉树的右视图 - 力扣&#xff08;LeetCode&#xff09; 思路 右视图是指从树的右侧看&#xff0c;对于每一层&#xff0c;只能看到该层最右边的节点。实现思路是&#xff1a; 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

Java求职者面试指南:计算机基础与源码原理深度解析

Java求职者面试指南&#xff1a;计算机基础与源码原理深度解析 第一轮提问&#xff1a;基础概念问题 1. 请解释什么是进程和线程的区别&#xff1f; 面试官&#xff1a;进程是程序的一次执行过程&#xff0c;是系统进行资源分配和调度的基本单位&#xff1b;而线程是进程中的…...