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.
相关推荐
芝麻开门-新起点2 分钟前
第13-1章 Python地理空间开发
开发语言·python
肥大毛24 分钟前
C++入门学习---结构体
开发语言·c++·学习
小明记账簿24 分钟前
JavaScript浮点数精度问题及解决方案
开发语言·javascript·ecmascript
南棱笑笑生40 分钟前
20251213给飞凌OK3588-C开发板适配Rockchip原厂的Buildroot【linux-6.1】系统时适配type-C0
linux·c语言·开发语言·rockchip
月屯1 小时前
Pandoc 之--pdf-engine
java·开发语言·pdf
晨星3341 小时前
使用 IntelliJ IDEA 轻松连接 Java 与 MySQL 8 数据库
java·开发语言·数据库
古城小栈1 小时前
Java 在 Web3 时代的新定位
java·开发语言·web3
何中应1 小时前
【面试题-5】设计模式
java·开发语言·后端·设计模式·面试题
Kiri霧1 小时前
Go包基础与使用指南
开发语言·后端·golang
小猪猪屁1 小时前
顺序表与链表:头插法与尾插法详解
c语言·数据结构·c++