设计模式:
涉及模式基本分为
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;
}