C++设计模式(策略模式)

一、介绍

1.动机

在软件构建过程中,某些对象使用的算法可能多种多样、经常改变,如果将这些算法都编码到对象中,将会使对象变得异常复杂;而且有时候支持不使用的算法也是一个性能负担。

如何在运行时根据需要透明地更改对象的算法,将算法与对象本身解耦,从而避免上述问题?

2.定义

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

3.结构图

4.要点总结

Strategy及其子类为组件提供了一系列可重用的算法,从而可以使得类型在运行时根据需要在各个算法之间进行切换。

Strategy模式提供了用条件判断语句以外的另一种选择,消除条件判断语句,就是在解耦合。含有许多条件判断语句的代码通常都需要Strategy模式。

如果Strategy对象没有实例变量,那么各个上下文可以共享同一个Strategy对象,从而节省对象开销。

二、策略模式

1.概念

策略模式允许在运行时动态地改变算法或策略的选择,其核心在于将算法与使用它的客户端代码解耦,使得算法的变化不会影响客户端的使用。

①优点:

  • 策略模式使得客户端可以在运行时选择合适的算法,动态改变对象的行为,提高了灵活性。
  • 策略模式可以减少大量的条件分支语句,使代码更清晰、简洁,易于维护。
  • 使用策略模式新增算法时无需修改现有代码,符合开闭原则,使系统更易于扩展。
  • 策略模式使得每个算法都有自己的类,符合单一职责原则,提高了代码的可读性和可维护性。

②缺点:

  • 客户端必须了解所有的策略类,以便在运行时选择合适的策略。
  • 使用策略模式会增加类的数量,可能会导致类的膨胀。
  • 如果策略类设计不当,可能会引入过多的细粒度策略类,导致系统过度复杂。

2.实现要点

  • 策略:定义一个抽象策略类,包含算法的通用接口。
  • 具体策略:继承自抽象策略类,用于实现策略接口,每个具体策略类代表一个算法。
  • 上下文:上下文是一个包含策略对象的类,使用组合的方式,通常持有一个指向策略对象的指针,负责将客户端的请求委派给具体的策略对象来执行,同时提供一个接口来切换策略。

3.示例

cpp 复制代码
//出行策略抽象类
class TravelStrategy {
public:
	virtual void travel() = 0;
	virtual ~TravelStrategy() {}
};

//步行策略类
class WalkStrategy :public TravelStrategy {
public:
	virtual void travel() override {
		cout << "Walk to destination." << endl;
	}
};

//骑自行车策略类
class BikeStrategy : public TravelStrategy {
public:
	virtual void travel() override {
		cout << "Ride bike to destination." << endl;
	}
};

//坐公交车策略类
class BusStrategy :public TravelStrategy {
public:
	virtual void travel() override {
		cout << "Take bus to destination." << endl;
	}
};

//出行者(上下文类)
class Traveler {
public:
	void setStrategy(TravelStrategy* ts) {  //切换策略
		strategy = ts;
	}
	void gotoDestination() {  //执行策略
		if (strategy)
			strategy->travel();
	}

private:
	TravelStrategy* strategy;
};

测试代码:

cpp 复制代码
WalkStrategy* walk = new WalkStrategy();
TravelStrategy* bike = new BikeStrategy();
unique_ptr<BusStrategy> bus = make_unique<BusStrategy>();

Traveler* traveler = new Traveler();
traveler->setStrategy(walk);
traveler->gotoDestination();
traveler->setStrategy(bike);
traveler->gotoDestination();
traveler->setStrategy(bus.get());
traveler->gotoDestination();

delete walk;
delete bike;
delete traveler;

输出结果:

bash 复制代码
Walk to destination.
Ride bike to destination.
Take bus to destination.
相关推荐
2601_9669496526 分钟前
如何根据研究的起止时间截取分钟级行情?Python 实战与 QuantDash 数据处理指南
开发语言·python·pandas·量化交易·1024程序员节·股票数据·quantdash
晨曦中的暮雨2 小时前
限流算法——固定窗口、滑动窗口、漏桶、令牌桶
java·开发语言·算法
喵了几个咪3 小时前
GoWind CMS 拆解:在 Go 里给 TipTap 搭一套 Yjs 协同后端
开发语言·后端·golang
程序员清风3 小时前
数据处理脚本工程化:日志、配置、命令行与测试
服务器·开发语言·数据库
知守观5 小时前
设计模式实战:从真实老项目中看标准模板方法与工厂的落地
java·spring·设计模式
2601_962885725 小时前
如何用 Python 把 K 线重采样成任意周期?
开发语言·python
choumin5 小时前
C++中万能引用与std::forward的作用和用法
c++·万能引用·std forward
Wang's Blog5 小时前
Java 项目实战: 交友项目 - 圈子功能实现:总结
java·开发语言·交友
下一站春风里6 小时前
位运算完整学习笔记:按位与(&)+ 异或(^)
开发语言·c++·算法
天外飞雨道沧桑7 小时前
我在浏览器里练了一个 792 参数的大模型,它学会了补全 JavaScript
开发语言·javascript·ai·ecmascript·ai编程