设计模式学习记录

本文详细介绍了设计模式中的行为型(策略、访问者)、创建型(工厂)、结构型(装饰者)以及开放-封闭原则、单一职责原则等原则的应用,以购物优惠、验证方式和信息通知为例,展示了这些模式在实际编程中的运用和优势。
摘要由CSDN通过智能技术生成

设计模式:

涉及模式基本分为
1.行为型:关注对象之间的通信和协作完成同一任务
2.创建型:关注对象如果创建,通常涉及对象如何实例化、对象的组合等
3.结构型:灵活定义对象的关系

策略模式(行为型):

  • 1.在需要策略的类A里面组合一个策略对象B,并调用这个策略对象的方法。策略需要通过A自身内部的方法来设置具体的策略,然后在需要的方法内部使用该策略的方法
  • 2.使用场景:同一物品不同价格策略
  • 体现原则

1.(OCP):策略者模式符合开放-封闭原则,它通过将具体的算法或行为封装到不同的策略类中,使得客户端能够在运行时选择不同的策略,而不需要修改客户端代码。客户端只需要针对抽象策略接口编程,通过依赖倒置原则,将具体策略的选择交给客户端,从而实现了扩展性和灵活性。
2.(SRP):策略者模式遵循单一职责原则,它将不同的算法或行为封装到不同的策略类中,每个策略类只负责实现一种具体的算法或行为。这样使得每个策略类都具有清晰的职责,易于理解和维护。

  • 拿购物优惠举例:
class DiscountStrategy {        //优惠基类,作为策略
public:
    virtual double applyDiscount(double amount) const = 0;
    virtual ~DiscountStrategy() {}
};
class PercentageDiscount : public DiscountStrategy {
public:
    explicit PercentageDiscount(double percentage) : percentage(percentage) {}

    double applyDiscount(double amount) const override {
        return amount * (1 - percentage);
    }

private:
    double percentage;
};
class FlatDiscount : public DiscountStrategy {      //子类,实现不同优惠需求
public:
    explicit FlatDiscount(double discountAmount) : discountAmount(discountAmount) {}

    double applyDiscount(double amount) const override {
        return amount - discountAmount;
    }

private:
    double discountAmount;
};
class ShoppingCart {        //需要策略的类
public:
    ShoppingCart(double amount, std::shared_ptr<DiscountStrategy> strategy)
        : amount(amount), strategy(strategy) {}
    double calculateTotal() const {
        return strategy->applyDiscount(amount);
    }
private:
    double amount;
    std::shared_ptr<DiscountStrategy> strategy;     //需要策略的类里包含策略类的指针也算
};
int main() {
    double totalAmount = 100.0;
    std::shared_ptr<DiscountStrategy> discountStrategy = std::make_shared<PercentageDiscount>(0.1); // 10% 折扣
    ShoppingCart cart(totalAmount, discountStrategy);   //在这里可以自由更换策略,实现策略和需要策略的类互不干涉
    double totalAfterDiscount = cart.calculateTotal();
    std::cout << "Total amount after discount: " << totalAfterDiscount << std::endl;
    return 0;
}

访问者模式(行为型):

  • 定义:访问者A和访问者B内部的方法中用到对方的对象参数,使用该参数的方法进行需要的操作。具体的访问者通过传参的不同来实现多态。访问者模式被称为双重分派技术,核心是将数据的存储和操作解除解耦。
  • 场景:数据分析时普通用户和高级用户时,对不同用户有不同的访问行为
  • 缺点:因为重载函数只有静态的,代码实现复杂,可读性较差,了解即可
  • 代码示例:
#include <string>
class User {        //用户基类,被访问者
public:
    virtual void accept(class Visitor& v) = 0;
    virtual ~User() {}
    virtual std::string getName() const = 0;
    virtual int getAge() const = 0;
};
class BasicUser : public User {         //普通用户
public:
    BasicUser(std::string name, int age) : name(name), age(age) {}

    void accept(Visitor& v) override {
        v.visitBasicUser(*this);
    }

    std::string getName() const override {
        return name;
    }

    int getAge() const override {
        return age;
    }
private:
    std::string name;
    int age;
};
class PremiumUser : public User {       //高级用户
public:
    PremiumUser(std::string name, int age, std::string premiumInfo) : name(name), age(age), premiumInfo(premiumInfo) {}

    void accept(Visitor& v) override {
        v.visitPremiumUser(*this);
    }

    std::string getName() const override {
        return name;
    }

    int getAge() const override {
        return age;
    }

    std::string getPremiumInfo() const {
        return premiumInfo;
    }
private:
    std::string name;
    int age;
    std::string premiumInfo;
};
#include "user.h" // 引入 User 类的前置声明
class Visitor {     //访问者
public:
    virtual void visitBasicUser(BasicUser& user) = 0;
    virtual void visitPremiumUser(PremiumUser& user) = 0;
    // 可以添加更多的 visit 方法...
};


装饰者模式(结构型):

  • 组件A和装饰B中,A和B都继承与抽象组件C,在B中还组合有实现了抽象组件的对象c(内部的类,C c)。假设A和B都实现C中的mathod,调用路程是:
  • 1.一般创建B的上转型对象来进行操作,如

C c=new A(); //此时c的属性是A,方法调用的也是A的mathod

  • 2.然后创建一个对象B(接收参数C),并将c用装饰B赋值,如

c= new B©; //此时c的属性是B,方法调用的是B重新实现的mathod

  • 3.调用方法

c.mathod();

在上面的过程第二部中,装饰B将接收的c参数赋值给自己内部的c。然后在第三步中,c调用的方法会是B中重新实现的方法,该重新实现的方法通常包含原有的c的方法(通过B内部赋值的c来调用)加上装饰的部分,实现不需要修改A的方法增加了一部分,所以叫装饰

  • 体现原则:OCP、SRP、LoD和DIP

1.(OCP):它允许在不修改现有对象的情况下动态地扩展其功能。通过将对象包装在装饰者对象中,并且让装饰者对象实现与原始对象相同的接口,可以在运行时动态地添加新的装饰者对象来扩展对象的行为,而不需要修改原始对象的代码。这样使得系统具有良好的可扩展性和可维护性。
2.(SRP):它将功能的扩展分散到不同的装饰者对象中,每个装饰者对象只负责特定的功能扩展。原始对象和装饰者对象都应该遵循单一职责原则,每个对象只负责自身的核心功能,使得系统中的对象职责清晰、可维护。
3.(LoD)在装饰者模式中,装饰者类和被装饰者类都实现了同一个抽象接口,因此可以在程序中将装饰者对象替换为被装饰者对象,而不会引起错误。
具体来说,装饰者模式中的装饰者类继承自抽象组件(Component)类,同时也可以作为组件类的一种替代品使用。装饰者类不仅可以对组件对象进行装饰,还可以替代组件对象在使用时,而且在使用装饰者对象时,客户端代码不需要关心具体是使用了装饰者还是原始组件,可以将二者视为同一种类型,达到无缝替换的效果。
4.(DIP):装饰者模式通过抽象组件类作为装饰者和被装饰者的共同接口,实现了依赖倒置原则。高层模块(客户端代码)依赖于抽象接口,而不依赖于具体的实现类。这样使得系统更加灵活,可以在运行时动态地替换和组合装饰者对象。


工厂模式(创建型):

  • 定义:核心是:product=creator.getproduct();
    product不需要关心哪一个产品,需要改变产品时只需要改变creator的方法就好,实现用户代码和特定子类代码的解耦,用户是需要使用这段代码的程序员,好处是你使用别人写的creator时不需要关系如何改变creator,减少阅读成本
  • 场景:不同的验证方式,
#include <iostream>
#include <memory>
#include <string>
// Abstract base class for authentication
class Authentication {      //验证器的基类
public:
    virtual void authenticate() = 0;
    virtual ~Authentication() {}
};
// Concrete authentication classes
class AuthorizationCodeAuthentication : public Authentication {
public:
    void authenticate() override {
        std::cout << "Performing Authorization Code Authentication" << std::endl;
    }
};
class ImplicitAuthentication : public Authentication {
public:
    void authenticate() override {
        std::cout << "Performing Implicit Authentication" << std::endl;
    }
};
class PasswordCredentialsAuthentication : public Authentication {
public:
    void authenticate() override {
        std::cout << "Performing Password Credentials Authentication" << std::endl;
    }
};
class ClientCredentialsAuthentication : public Authentication {
public:
    void authenticate() override {
        std::cout << "Performing Client Credentials Authentication" << std::endl;
    }
};
class AuthenticationFactory {   //工厂
public:
    std::unique_ptr<Authentication> createAuthentication(const std::string& type) {
        if (type == "authorization_code") {
            return std::make_unique<AuthorizationCodeAuthentication>();
        } else if (type == "implicit") {
            return std::make_unique<ImplicitAuthentication>();
        } else if (type == "password_credentials") {
            return std::make_unique<PasswordCredentialsAuthentication>();
        } else if (type == "client_credentials") {
            return std::make_unique<ClientCredentialsAuthentication>();
        } else {
            return nullptr;
        }
    }
};
int main() {
    AuthenticationFactory factory;
    std::unique_ptr<Authentication> auth1 = factory.createAuthentication("authorization_code");     //单一个工厂返回不同验证器
    std::unique_ptr<Authentication> auth2 = factory.createAuthentication("implicit");
    std::unique_ptr<Authentication> auth3 = factory.createAuthentication("password_credentials");
    std::unique_ptr<Authentication> auth4 = factory.createAuthentication("client_credentials");
    auth1->authenticate();
    auth2->authenticate();
    auth3->authenticate();
    auth4->authenticate();
    return 0;
}

观察者模式(行为型)

  • 定义:观察者和被观察者分离,通常一个被观察者,多个观察者,当被观察者发生变化时通知观察者,观察者执行各自的行为。如果观察者过多,例如通知全服玩家的那种,就不考虑观察者模式而是使用消息队列
  • 场景:邮件,异步通知,ui更新(如qt的信号机制)
#include <iostream>
#include <vector>
#include <string>
class Publisher {       //被观察者
public:
    void publish(const std::string& message) {
        std::cout << "Publishing message: " << message << std::endl;
        // 将消息发布到消息队列或者消息通道中
    }
};
class Subscriber {      //观察者
public:
    void receive(const std::string& message) {
        std::cout << "Received message: " << message << std::endl;
    }
};
int main() {
    Publisher publisher;
    std::vector<Subscriber> subscribers = {
        Subscriber(),
        Subscriber(),
        Subscriber()
    };
    publisher.publish("Hello, World!");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值