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.
相关推荐
JnnRrfmk几秒前
四旋翼飞行器轨迹跟踪仿真 控制 路径规划与轨迹优化MATLAB四旋翼飞行器仿真无人机simul...
c++
uoKent3 分钟前
Qt C++项目基础
c++·qt
chao1898445 分钟前
基于字典缩放的属性散射中心参数提取算法与MATLAB实现
开发语言·算法·matlab
小尧嵌入式9 分钟前
【Linux开发四】Linux中概念|MobaXterm和Filezilla软件使用|线程|互斥锁|读写锁
linux·运维·服务器·开发语言·数据结构
a努力。10 分钟前
Spring Boot 4 全面拥抱 Jackson 3
java·运维·开发语言·spring boot·后端·spring·jenkins
晚霞的不甘18 分钟前
Flutter for OpenHarmony 布局探秘:从理论到实战构建交互式组件讲解应用
开发语言·前端·flutter·正则表达式·前端框架·firefox·鸿蒙
爱吃大芒果20 分钟前
Flutter for OpenHarmony核心组件学习: MaterialApp、Scaffold 两大基础组件以及有无状态组件
开发语言·学习·flutter
茶本无香22 分钟前
设计模式之七—装饰模式(Decorator Pattern)
java·设计模式·装饰器模式
做科研的周师兄28 分钟前
【MATLAB 实战】栅格数据一元线性回归计算(NDVI 趋势分析)| 附完整可运行代码
开发语言·matlab·线性回归
仰泳的熊猫29 分钟前
题目1431:蓝桥杯2014年第五届真题-分糖果
数据结构·c++·算法·蓝桥杯