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.
相关推荐
rit84324994 小时前
基于MATLAB的模糊图像复原
开发语言·matlab
fie88894 小时前
基于MATLAB的声呐图像特征提取与显示
开发语言·人工智能
_extraordinary_5 小时前
Java SpringMVC(二) --- 响应,综合性练习
java·开发语言
Larry_Yanan6 小时前
QML学习笔记(三十四)QML的GroupBox、RadioButton
c++·笔记·qt·学习·ui
@。1246 小时前
对于灰度发布(金丝雀发布)的了解
开发语言·前端
程序员老舅6 小时前
干货|腾讯 Linux C/C++ 后端开发岗面试
linux·c语言·c++·编程·大厂面试题
程序员Aries6 小时前
自定义网络协议与序列化/反序列化
linux·网络·c++·网络协议·程序人生
Pafey7 小时前
MFC中一个类的成员变量值自动被篡改:多重继承带来的问题
c++·mfc
hsjkdhs7 小时前
C++之多层继承、多源继承、菱形继承
开发语言·c++·算法
Full Stack Developme7 小时前
Python Redis 教程
开发语言·redis·python