• 常用的二十种设计模式(上)-C++


    C++中常用的设计模式有很多,设计模式是解决常见问题的经过验证的最佳实践。以下是一些常用的设计模式:

    1. 单例模式(Singleton):确保一个类只有一个实例,并提供一个全局访问点。
    2. 工厂模式(Factory):用于创建对象,而不需要指定具体类。
    3. 抽象工厂模式(Abstract Factory):提供一组相关或相互依赖的对象,而不指定其具体类。
    4. 建造者模式(Builder):将一个复杂对象的构建与其表示分离,使相同的构建过程可以创建不同的表示。
    5. 原型模式(Prototype):通过克隆已有对象来创建新对象,以避免直接使用构造函数。
    6. 适配器模式(Adapter):将一个接口转换成另一个客户希望使用的接口。
    7. 装饰器模式(Decorator):动态地给一个对象添加一些额外的职责,而不需要子类化。
    8. 代理模式(Proxy):为其他对象提供一个代理以控制对这个对象的访问。
    9. 观察者模式(Observer):定义了一种一对多的依赖关系,当一个对象状态改变时,所有依赖它的对象都会得到通知。
    10. 策略模式(Strategy):定义一系列算法,封装它们,使它们可以相互替换。
    11. 命令模式(Command):将一个请求封装成一个对象,从而允许使用不同的请求、队列或日志请求。
    12. 状态模式(State):允许对象在其内部状态改变时改变其行为。
    13. 模板方法模式(Template Method):定义算法的骨架,允许子类重写其中的步骤。
    14. 访问者模式(Visitor):表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
    15. 组合模式(Composite):将对象组合成树形结构以表示“部分-整体”的层次结构。
    16. 迭代器模式(Iterator):提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。
    17. 中介者模式(Mediator):定义一个对象,封装一系列对象之间的交互,从而降低对象之间的耦合度。
    18. 备忘录模式(Memento):不破坏封装的前提下,捕获一个对象的内部状态,并在对象之外保存这个状态。
    19. 桥接模式(Bridge):将抽象部分与它的实现部分分离,使它们可以独立变化。
    20. 解释器模式(Interpreter):给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

    这些设计模式都有特定的应用场景,可以根据问题的性质选择合适的设计模式来解决。设计模式有助于提高代码的可维护性、可扩展性和复用性。

    1.单例模式

    提供所有设计模式的 C++ 示例代码是一个庞大的任务,但我可以为您提供一个示例,演示如何使用 C++ 实现一个常见的设计模式——单例模式(Singleton)。

    单例模式(Singleton) 确保一个类只有一个实例,并提供全局访问点。以下是一个基本的单例模式示例:

    #include 
    
    class Singleton {
    public:
        static Singleton& getInstance() {
            static Singleton instance;  // 静态局部变量确保只初始化一次
            return instance;
        }
    
        void doSomething() {
            std::cout << "Singleton is doing something." << std::endl;
        }
    
    private:
        Singleton() {}  // 构造函数私有,只能通过 getInstance() 获取实例
    };
    
    int main() {
        // 获取 Singleton 实例
        Singleton& singleton = Singleton::getInstance();
        singleton.doSomething();
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    在这个示例中,Singleton 类的构造函数是私有的,这意味着外部无法直接创建 Singleton 对象。通过 getInstance() 静态成员函数,我们可以获取到单一的 Singleton 实例。这确保了只有一个实例存在。
    单例模式常用于需要共享资源或控制访问某些全局状态的情况。在实际项目中,设计模式的选择会根据具体需求和架构决策,不同的模式可能会以不同的方式被实现和使用。

    2.工厂模式

    工厂模式(Factory Pattern)是一种创建型设计模式,用于创建对象而无需指定对象的具体类。工厂模式通过定义一个共同的接口,由不同的工厂子类来实现,并根据不同的情况返回不同的具体对象。

    以下是一个简单的工厂模式的 C++ 示例:

    #include 
    
    // 抽象产品类
    class Product {
    public:
        virtual void use() = 0;
    };
    
    // 具体产品类 A
    class ConcreteProductA : public Product {
    public:
        void use() override {
            std::cout << "Product A in use." << std::endl;
        }
    };
    
    // 具体产品类 B
    class ConcreteProductB : public Product {
    public:
        void use() override {
            std::cout << "Product B in use." << std::endl;
        }
    };
    
    // 抽象工厂类
    class Factory {
    public:
        virtual Product* createProduct() = 0;
    };
    
    // 具体工厂类 A,用于创建 ProductA
    class ConcreteFactoryA : public Factory {
    public:
        Product* createProduct() override {
            return new ConcreteProductA();
        }
    };
    
    // 具体工厂类 B,用于创建 ProductB
    class ConcreteFactoryB : public Factory {
    public:
        Product* createProduct() override {
            return new ConcreteProductB();
        }
    };
    
    int main() {
        // 使用具体工厂类 A 创建产品 A
        Factory* factoryA = new ConcreteFactoryA();
        Product* productA = factoryA->createProduct();
        productA->use();
    
        // 使用具体工厂类 B 创建产品 B
        Factory* factoryB = new ConcreteFactoryB();
        Product* productB = factoryB->createProduct();
        productB->use();
    
        delete factoryA;
        delete factoryB;
        delete productA;
        delete productB;
    
        return 0;
    }
    
    • 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

    在这个示例中,我们定义了抽象产品类 Product,有两个具体的产品类 ConcreteProductAConcreteProductB,它们都继承自 Product。然后,我们定义了抽象工厂类 Factory,有两个具体工厂类 ConcreteFactoryAConcreteFactoryB,它们分别负责创建不同的产品。

    通过使用工厂模式,我们可以根据具体的需求选择不同的工厂类来创建产品,而无需关心产品的具体类是什么。这提供了灵活性,允许我们轻松扩展和替换具体产品和工厂类。

    这是一个简单的示例,实际中工厂模式可用于更复杂的对象创建需求。工厂模式常用于创建对象的场景,特别是在代码中需要降低耦合性时非常有用。

    3.抽象工厂模式

    抽象工厂模式(Abstract Factory Pattern)是一种创建型设计模式,它提供了一个接口,用于创建一系列相关或依赖的对象,而不需要指定它们的具体类。抽象工厂模式的核心思想是为每个产品族(相关的一组产品)定义一个抽象工厂,然后在每个具体工厂中实现该抽象工厂。

    以下是一个简单的抽象工厂模式的 C++ 示例:

    #include 
    
    // 抽象产品 A
    class AbstractProductA {
    public:
        virtual void useA() = 0;
    };
    
    // 具体产品 A1
    class ConcreteProductA1 : public AbstractProductA {
    public:
        void useA() override {
            std::cout << "Product A1 in use." << std::endl;
        }
    };
    
    // 具体产品 A2
    class ConcreteProductA2 : public AbstractProductA {
    public:
        void useA() override {
            std::cout << "Product A2 in use." << std::endl;
        }
    };
    
    // 抽象产品 B
    class AbstractProductB {
    public:
        virtual void useB() = 0;
    };
    
    // 具体产品 B1
    class ConcreteProductB1 : public AbstractProductB {
    public:
        void useB() override {
            std::cout << "Product B1 in use." << std::endl;
        }
    };
    
    // 具体产品 B2
    class ConcreteProductB2 : public AbstractProductB {
    public:
        void useB() override {
            std::cout << "Product B2 in use." << 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() {
        // 使用具体工厂 1 创建产品 A 和 B
        AbstractFactory* factory1 = new ConcreteFactory1();
        AbstractProductA* productA1 = factory1->createProductA();
        AbstractProductB* productB1 = factory1->createProductB();
    
        productA1->useA();
        productB1->useB();
    
        // 使用具体工厂 2 创建产品 A 和 B
        AbstractFactory* factory2 = new ConcreteFactory2();
        AbstractProductA* productA2 = factory2->createProductA();
        AbstractProductB* productB2 = factory2->createProductB();
    
        productA2->useA();
        productB2->useB();
    
        delete factory1;
        delete productA1;
        delete productB1;
    
        delete factory2;
        delete productA2;
        delete productB2;
    
        return 0;
    }
    
    • 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

    在这个示例中,我们定义了两个抽象产品类 AbstractProductAAbstractProductB,以及它们的具体实现类。然后,我们定义了抽象工厂类 AbstractFactory,它包括两个工厂方法,分别用于创建产品 A 和产品 B。具体工厂类 ConcreteFactory1ConcreteFactory2 分别实现了 AbstractFactory,用于创建不同的产品族。

    抽象工厂模式允许我们在不知道具体产品类的情况下创建一组相关产品,这对于需要保持产品族之间的一致性非常有用。此模式还支持易于替换整个产品族,以满足不同的需求。

    4.建造者模式

    建造者模式(Builder Pattern)是一种创建型设计模式,用于构建一个复杂对象,将构造过程和表示分离。通常情况下,该模式包括一个 Director(指挥者)类、一个抽象 Builder(建造者)接口和具体的 Builder 实现类。

    以下是一个简单的建造者模式的 C++ 示例:

    #include 
    #include 
    
    // 产品类,即要构建的复杂对象
    class Product {
    public:
        void setPartA(const std::string& partA) {
            partA_ = partA;
        }
    
        void setPartB(const std::string& partB) {
            partB_ = partB;
        }
    
        void setPartC(const std::string& partC) {
            partC_ = partC;
        }
    
        void show() {
            std::cout << "Product parts: " << partA_ << ", " << partB_ << ", " << partC_ << std::endl;
        }
    
    private:
        std::string partA_;
        std::string partB_;
        std::string partC_;
    };
    
    // 抽象 Builder 接口
    class Builder {
    public:
        virtual void buildPartA() = 0;
        virtual void buildPartB() = 0;
        virtual void buildPartC() = 0;
        virtual Product getResult() = 0;
    };
    
    // 具体 Builder 实现
    class ConcreteBuilder : public Builder {
    public:
        ConcreteBuilder() {
            product_ = new Product();
        }
    
        void buildPartA() override {
            product_->setPartA("Part A");
        }
    
        void buildPartB() override {
            product_->setPartB("Part B");
        }
    
        void buildPartC() override {
            product_->setPartC("Part C");
        }
    
        Product getResult() override {
            return *product_;
        }
    
    private:
        Product* product_;
    };
    
    // 指挥者类,负责构建产品
    class Director {
    public:
        Director(Builder* builder) : builder_(builder) {}
    
        Product construct() {
            builder_->buildPartA();
            builder_->buildPartB();
            builder_->buildPartC();
            return builder_->getResult();
        }
    
    private:
        Builder* builder_;
    };
    
    int main() {
        ConcreteBuilder builder;
        Director director(&builder);
    
        Product product = director.construct();
        product.show();
    
        return 0;
    }
    
    • 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

    在这个示例中,我们有一个产品类 Product,包括三个部分。我们定义了抽象 Builder 接口,包括构建每个部分的方法和获取最终产品的方法。具体 Builder 类 ConcreteBuilder 实现了 Builder 接口,构建了 Product 的各个部分。指挥者类 Director 负责指导 Builder 构建产品。

    使用建造者模式,我们可以按照不同的需求构建不同的产品,而不必关心构建的细节。这种模式尤其适用于构建复杂对象,帮助将构建过程和表示分离,提高了可维护性和可扩展性。

    5.原型模式

    原型模式(Prototype Pattern)是一种创建型设计模式,其主要思想是通过复制现有对象(原型)来创建新对象,而不需要从头开始构建。这种模式通常用于创建成本高昂或复杂的对象,同时可以保持对象的不变性。原型模式基于对象的克隆,可以分为浅拷贝和深拷贝两种。

    以下是一个简单的原型模式的 C++ 示例:

    #include 
    #include 
    
    // 原型类
    class Prototype {
    public:
        virtual Prototype* clone() = 0;
        virtual void print() = 0;
    };
    
    // 具体原型类 A
    class ConcretePrototypeA : public Prototype {
    public:
        Prototype* clone() override {
            return new ConcretePrototypeA(*this); // 深拷贝
        }
    
        void print() override {
            std::cout << "ConcretePrototypeA" << std::endl;
        }
    };
    
    // 具体原型类 B
    class ConcretePrototypeB : public Prototype {
    public:
        Prototype* clone() override {
            return new ConcretePrototypeB(*this); // 深拷贝
        }
    
        void print() override {
            std::cout << "ConcretePrototypeB" << std::endl;
        }
    };
    
    int main() {
        Prototype* originalA = new ConcretePrototypeA();
        Prototype* originalB = new ConcretePrototypeB();
    
        // 克隆原型对象
        Prototype* cloneA = originalA->clone();
        Prototype* cloneB = originalB->clone();
    
        originalA->print();
        cloneA->print();
    
        originalB->print();
        cloneB->print();
    
        delete originalA;
        delete cloneA;
        delete originalB;
        delete cloneB;
    
        return 0;
    }
    
    • 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

    在这个示例中,我们定义了一个抽象原型类 Prototype,包括克隆方法 clone 和打印方法 print。然后,我们创建了两个具体的原型类 ConcretePrototypeAConcretePrototypeB,它们实现了克隆方法,并在打印方法中展示自己的类型。

    main 函数中,我们首先创建原型对象 originalAoriginalB,然后通过调用它们的 clone 方法,创建了相应的克隆对象 cloneAcloneB。这些克隆对象与原型对象具有相同的状态,但是是独立的对象。

    原型模式允许我们根据需要克隆对象,而不必重新创建。这对于创建成本高昂或复杂的对象,以及需要保持对象不变性的情况非常有用。需要注意的是,深拷贝和浅拷贝的选择取决于对象内部的状态和结构。在实际应用中,可能需要自定义克隆方法以适应特定需求。

    6.适配器模式

    适配器模式(Adapter Pattern)是一种结构型设计模式,它允许一个类的接口与另一个类的接口兼容。适配器模式主要用于解决两个已有接口之间的不匹配问题,使它们可以一起工作,而不需要修改它们的源代码。

    适配器模式有两种主要类型:类适配器和对象适配器。

    类适配器 使用多重继承,它继承了被适配类并实现了目标接口。

    对象适配器 维护一个被适配类的实例,并实现了目标接口,然后委托被适配类的实例来执行相应的操作。

    以下是一个简单的对象适配器模式的 C++ 示例:

    #include 
    
    // 目标接口
    class Target {
    public:
        virtual void request() = 0;
    };
    
    // 被适配类
    class Adaptee {
    public:
        void specificRequest() {
            std::cout << "Adaptee's specific request." << std::endl;
        }
    };
    
    // 对象适配器
    class Adapter : public Target {
    public:
        Adapter(Adaptee* adaptee) : adaptee_(adaptee) {}
    
        void request() override {
            adaptee_->specificRequest();
        }
    
    private:
        Adaptee* adaptee_;
    };
    
    int main() {
        Adaptee adaptee;
        Target* adapter = new Adapter(&adaptee);
    
        adapter->request();
    
        delete adapter;
    
        return 0;
    }
    
    • 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

    在这个示例中,我们有一个目标接口 Target,包括 request 方法。我们还有一个被适配类 Adaptee,它包括 specificRequest 方法,但它的接口与 Target 不兼容。

    然后,我们创建了一个对象适配器 Adapter,它实现了 Target 接口,并维护了一个 Adaptee 的实例。在 Adapterrequest 方法中,我们将调用委托给 AdapteespecificRequest 方法,从而使 Adaptee 可以与 Target 接口兼容。

    适配器模式在现实中的应用非常广泛,特别是在将旧系统与新系统集成或者使用第三方库时,它可以起到很好的桥梁作用,以确保不同接口之间的兼容性。

    类适配器

    类适配器模式使用多重继承来实现适配,它继承了被适配类并实现了目标接口。以下是一个简单的类适配器模式的 C++ 示例:

    #include 
    
    // 目标接口
    class Target {
    public:
        virtual void request() = 0;
    };
    
    // 被适配类
    class Adaptee {
    public:
        void specificRequest() {
            std::cout << "Adaptee's specific request." << std::endl;
        }
    };
    
    // 类适配器,继承自 Adaptee 和实现 Target 接口
    class Adapter : public Adaptee, public Target {
    public:
        void request() override {
            specificRequest(); // 调用 Adaptee 的方法
        }
    };
    
    int main() {
        Target* adapter = new Adapter();
    
        adapter->request();
    
        delete adapter;
    
        return 0;
    }
    
    • 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

    在这个示例中,我们有一个目标接口 Target,包括 request 方法。我们还有一个被适配类 Adaptee,它包括 specificRequest 方法,但它的接口与 Target 不兼容。

    然后,我们创建了一个类适配器 Adapter,它继承自 Adaptee 并实现了 Target 接口。在 Adapterrequest 方法中,我们可以直接调用 specificRequest 方法,因为 Adapter 继承了 Adaptee

    类适配器模式使用多重继承,这使得它可以同时继承多个类,但也可能引入一些复杂性。适配器模式可用于解决现有系统的接口不兼容问题,同时不需要修改被适配类的源代码。

    7.装饰器模式

    装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许你通过将对象包装在装饰器类的实例中来动态地扩展其行为,而不需要修改其源代码。装饰器模式通常用于以下情况:

    1. 动态地给对象添加功能,而不是静态继承;
    2. 需要遵循开放/封闭原则,即对扩展是开放的,对修改是封闭的;
    3. 需要通过一系列可重用的装饰器来组合不同的行为。

    以下是一个简单的装饰器模式的 C++ 示例:

    #include 
    
    // 抽象组件接口
    class Component {
    public:
        virtual void operation() = 0;
    };
    
    // 具体组件
    class ConcreteComponent : public Component {
    public:
        void operation() override {
            std::cout << "ConcreteComponent operation." << std::endl;
        }
    };
    
    // 抽象装饰器
    class Decorator : public Component {
    public:
        Decorator(Component* component) : component_(component) {}
    
        void operation() override {
            component_->operation();
        }
    
    private:
        Component* component_;
    };
    
    // 具体装饰器 A
    class ConcreteDecoratorA : public Decorator {
    public:
        ConcreteDecoratorA(Component* component) : Decorator(component) {}
    
        void operation() override {
            Decorator::operation();
            std::cout << "ConcreteDecoratorA operation." << std::endl;
        }
    };
    
    // 具体装饰器 B
    class ConcreteDecoratorB : public Decorator {
    public:
        ConcreteDecoratorB(Component* component) : Decorator(component) {}
    
        void operation() override {
            Decorator::operation();
            std::cout << "ConcreteDecoratorB operation." << std::endl;
        }
    };
    
    int main() {
        Component* component = new ConcreteComponent();
        Component* decoratorA = new ConcreteDecoratorA(component);
        Component* decoratorB = new ConcreteDecoratorB(decoratorA);
    
        component->operation();  // 基本组件操作
        decoratorA->operation(); // 增加了装饰器 A 的操作
        decoratorB->operation(); // 增加了装饰器 A 和装饰器 B 的操作
    
        delete component;
        delete decoratorA;
        delete decoratorB;
    
        return 0;
    }
    
    • 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

    在这个示例中,我们有一个抽象组件接口 Component,包括 operation 方法。具体组件 ConcreteComponent 实现了这个接口。

    然后,我们定义了抽象装饰器 Decorator,它也实现了 Component 接口,但在 operation 方法中调用了包装的组件的 operation 方法。具体装饰器类 ConcreteDecoratorAConcreteDecoratorB 扩展了 Decorator 类,分别增加了特定的操作。

    main 函数中,我们创建了一个基本组件 component,然后依次用装饰器 decoratorAdecoratorB 包装它。通过这样的嵌套,我们可以动态地添加不同的行为,而不需要修改组件的源代码。

    装饰器模式允许我们以一种灵活的方式组合对象,以满足不同需求。这可以帮助我们遵循开放/封闭原则,同时保持代码的可维护性和可扩展性。

    8.代理模式

    代理模式(Proxy Pattern)是一种结构型设计模式,它允许你提供一个代理类,控制对其他对象的访问。代理模式通常用于以下情况:

    1. 远程代理:代理对象控制对远程对象的访问,例如通过网络。
    2. 虚拟代理:代理对象控制对创建开销大的对象的访问,只在需要时创建。
    3. 保护代理:代理对象控制对对象的访问权限,用于权限控制等。
    4. 智能引用:代理对象添加额外的逻辑,例如引用计数、懒加载等。

    以下是一个简单的代理模式的 C++ 示例:

    #include 
    
    // 抽象主题
    class Subject {
    public:
        virtual void request() = 0;
    };
    
    // 具体主题
    class RealSubject : public Subject {
    public:
        void request() override {
            std::cout << "RealSubject handles the request." << std::endl;
        }
    };
    
    // 代理
    class Proxy : public Subject {
    public:
        Proxy(Subject* realSubject) : realSubject_(realSubject) {}
    
        void request() override {
            if (checkAccess()) {
                realSubject_->request();
                logAccess();
            } else {
                std::cout << "Access denied." << std::endl;
            }
        }
    
    private:
        bool checkAccess() {
            // 检查访问权限的逻辑
            return true;
        }
    
        void logAccess() {
            // 记录访问日志的逻辑
            std::cout << "Access logged." << std::endl;
        }
    
        Subject* realSubject_;
    };
    
    int main() {
        RealSubject realSubject;
        Proxy proxy(&realSubject);
    
        proxy.request();
    
        return 0;
    }
    
    • 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

    在这个示例中,我们有一个抽象主题 Subject,包括 request 方法。具体主题 RealSubject 实现了这个接口,用于处理请求。

    然后,我们创建了代理 Proxy,它也实现了 Subject 接口。在 Proxyrequest 方法中,我们可以添加额外的逻辑,例如检查访问权限和记录访问日志。如果权限检查通过,它将委托给实际主题 RealSubject 来处理请求。

    代理模式使我们能够控制对对象的访问,同时可以添加各种额外的功能,例如权限控制、懒加载、缓存等。这对于保持代码的可维护性和可扩展性非常有帮助。

    9.观察者模式

    观察者模式(Observer Pattern)是一种行为型设计模式,它定义了一种一对多的依赖关系,使一个对象的状态发生变化时,其所有依赖者(观察者)都会收到通知并自动更新。观察者模式通常用于以下情况:

    1. 当一个对象的状态变化需要通知其他对象,而且这些对象的数量和类型是未知的。
    2. 当一个对象需要在不知道具体操作的情况下通知其他对象。
    3. 当一个对象需要维护一系列依赖关系,以便在状态变化时能够通知所有依赖者。

    观察者模式包含以下几个关键角色:

    1. 主题(Subject):主题是被观察的对象,它包含一组观察者对象,并提供方法来添加、删除和通知观察者。
    2. 观察者(Observer):观察者是接收主题通知的对象,它定义了更新方法,以便在主题状态发生变化时能够执行相应操作。

    以下是一个简单的观察者模式的 C++ 示例:

    #include 
    #include 
    
    // 观察者接口
    class Observer {
    public:
        virtual void update(const std::string& message) = 0;
    };
    
    // 主题接口
    class Subject {
    public:
        virtual void addObserver(Observer* observer) = 0;
        virtual void removeObserver(Observer* observer) = 0;
        virtual void notifyObservers(const std::string& message) = 0;
    };
    
    // 具体观察者
    class ConcreteObserver : public Observer {
    public:
        ConcreteObserver(const std::string& name) : name_(name) {}
    
        void update(const std::string& message) override {
            std::cout << name_ << " received message: " << message << std::endl;
        }
    
    private:
        std::string name_;
    };
    
    // 具体主题
    class ConcreteSubject : public Subject {
    public:
        void addObserver(Observer* observer) override {
            observers_.push_back(observer);
        }
    
        void removeObserver(Observer* observer) override {
            // 寻找并移除观察者
            auto it = std::find(observers_.begin(), observers_.end(), observer);
            if (it != observers_.end()) {
                observers_.erase(it);
            }
        }
    
        void notifyObservers(const std::string& message) override {
            for (Observer* observer : observers_) {
                observer->update(message);
            }
        }
    
    private:
        std::vector<Observer*> observers_;
    };
    
    int main() {
        ConcreteSubject subject;
        ConcreteObserver observer1("Observer 1");
        ConcreteObserver observer2("Observer 2");
    
        subject.addObserver(&observer1);
        subject.addObserver(&observer2);
    
        subject.notifyObservers("Hello, observers!");
    
        subject.removeObserver(&observer1);
    
        subject.notifyObservers("Observers after removal.");
    
        return 0;
    }
    
    • 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

    在这个示例中,我们定义了观察者接口 Observer 和主题接口 Subject,分别包括添加、移除和通知观察者的方法。然后,我们创建了具体的观察者类 ConcreteObserver 和具体的主题类 ConcreteSubject

    main 函数中,我们创建主题对象 subject 和两个观察者对象 observer1observer2。我们将观察者添加到主题中,然后主题通知观察者时,它们会接收到消息并执行相应的操作。

    观察者模式使对象之间的关系松散,允许主题和观察者之间的独立变化,同时保持了对象之间的协作。这种模式常用于实现事件处理、发布-订阅系统以及任何需要实现对象之间松耦合通信的情况。

    10.策略模式

    策略模式(Strategy Pattern)是一种行为型设计模式,它允许定义一系列算法,并将每个算法封装到独立的策略类中,使这些算法可以互相替换。策略模式的核心思想是将算法的选择与使用分离,从而实现更灵活的算法切换,同时不需要修改上下文类的代码。

    策略模式包含以下几个主要角色:

    1. 上下文(Context):上下文类包含一个策略接口的引用,它可以在运行时切换不同的策略对象,以实现不同的行为。上下文类不直接实现算法,而是将算法委托给策略对象。
    2. 策略(Strategy):策略是一个接口或抽象类,定义了一个算法族的接口,具体的策略类实现了这个接口,每个策略类代表一个具体的算法。

    使用策略模式的主要优点包括:

    • 算法的可独立替换性:可以在运行时切换算法,而不需要修改上下文类的代码。
    • 降低了上下文类的复杂性:上下文类只需要关注如何选择和使用策略,而不需要实现具体算法。
    • 提高了代码的可维护性和可扩展性:每个策略类可以独立开发和测试,容易新增新的策略。

    以下是一个简单的策略模式的 C++ 示例:

    #include 
    
    // 策略接口
    class Strategy {
    public:
        virtual void doOperation() = 0;
    };
    
    // 具体策略 A
    class ConcreteStrategyA : public Strategy {
    public:
        void doOperation() override {
            std::cout << "Using Strategy A" << std::endl;
        }
    };
    
    // 具体策略 B
    class ConcreteStrategyB : public Strategy {
    public:
        void doOperation() override {
            std::cout << "Using Strategy B" << std::endl;
        }
    };
    
    // 上下文
    class Context {
    public:
        Context(Strategy* strategy) : strategy_(strategy) {}
    
        void setStrategy(Strategy* strategy) {
            strategy_ = strategy;
        }
    
        void executeStrategy() {
            strategy_->doOperation();
        }
    
    private:
        Strategy* strategy_;
    };
    
    int main() {
        ConcreteStrategyA strategyA;
        ConcreteStrategyB strategyB;
    
        Context context(&strategyA);
        context.executeStrategy();
    
        context.setStrategy(&strategyB);
        context.executeStrategy();
    
        return 0;
    }
    
    • 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

    在这个示例中,我们有一个策略接口 Strategy,定义了算法族的接口。然后,我们创建了两个具体策略类 ConcreteStrategyAConcreteStrategyB,分别实现了不同的算法。

    上下文类 Context 包含一个策略对象的引用,它可以在运行时切换不同的策略。当调用 executeStrategy 方法时,上下文类会委托策略对象执行相应的算法。

    策略模式的应用范围很广,可以用于任何需要动态地选择算法的场景,例如排序算法、计算费用、路由策略等。

  • 相关阅读:
    pybind11 连接C++11和Python
    NVIDIA DPU — 安装部署
    C++封闭类
    扩散模型 - Diffusion Model【李宏毅2023】学习笔记 Part 1
    Linux开源防病毒引擎ClamAV
    Laravel框架 - IOC容器详解
    形态学 - 细化
    volatile关键字详解
    Python 概念集合浅谈
    2023年5月CSDN客服月报|解决5个重大问题和18个次要问题,采纳1个用户建议,处理2个用户需求
  • 原文地址:https://blog.csdn.net/weixin_39435970/article/details/133874738