设计模式回顾——策略模式(C++)

本文详细介绍了策略模式的概念、组成、作用及其实现过程。策略模式允许算法独立于使用它们的客户端,便于算法的选择和切换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


1 前言

  上一篇文章中对“适配器模式”进行概述与总结,分别描述了适配器模式含义、特点、优缺点、适用场景以及实现过程步骤,并以C++语言实现具体例子。本文描述另一常用的设计模式——策略模式。


相关文章:

设计模式回顾——原型模式
设计模式回顾——观察者模式
设计模式回顾——模板模式
设计模式回顾——策略模式
设计模式回顾——适配器模式
设计模式回顾——建造者模式
设计模式回顾——工厂模式
设计模式回顾——单例模式
设计模式回顾——设计模式概念与基本原则


2 什么是策略模式

  策略模式(Strategy Pattern),指的是定义一系列算法,并将这些算法封装到具有公共接口的一系列策略类中,使得它们可以动态自由切换。策略模式的本质是:分离算法,选择实现


  • 策略模式仅仅封装算法并提供接口,并不决定在何时、何地、使用何种算法;客户通过抽象接口访问具体算法

  • 策略模式将算法的责任和算法本身进行解耦,将算法的使用权由不同的对象管理,客户不关心算法的具体实现


2.1 策略模式组成

  策略模式由环境角色(Context)、抽象策略(Abstract Strategy)、具体策略(Concrete Strategy)、客户(Client)i四个要素组成。


  • 环境角色(Context), 持有一个对Abstract Strategy的引用,最终由客户端调用
  • 抽象策略(Abstract Strategy), 声明一个公共抽象接口,由不同算法类实现该接口;通过该接口,Context可以调用不同的算法
  • 具体策略(Concrete Strategy), 继承Abstract Strategy类,并实现抽象接口,提供具体算法
  • 客户(Client),客户通过调用Context调用策略算法,严格来说客户不属于策略模式的一部分

2.2 策略模式UML图

  根据策略模式的组成要素,以及它们之间的关系,画出策略模式的UML图如下。


在这里插入图片描述

策略模式UML图

2.3 策略模式作用

  • 让算法和对象分离,使得算法可以独立于使用它的客户而变化
  • 客户端可以根据外部条件来选择不同策略来解决不同问题
  • 替换“if-else”或者“switch-case”臃肿逻辑代码

3 策略模式优缺点

优点:

  • 灵活性好

    提供管理相关算法族的方法,策略类(算法)可自由切换,而不影响客户使用。

  • 易扩展

    新增策略(算法)时,只需要添加一个具体的策略类即可,不需改动原有代码和代码框架,符合“开闭原则“。

  • 代码结构清晰

    可以避免使用多重条件转移语句(“if-else”“switch-case”),逻辑性强,可读性和可维护性好。


条件语句的不足:

多重条件转移语句不易维护,特别是语句越来越多的场景。条件转移语句一般是把算法种类、算法选择与算法行为、算法本身的逻辑混合在一起,增、删、改算法时都需改动大量的代码,维护性差。


不足:

  • 暴露所有策略类
    客户端必须知道所有的策略类,才能根据具体场景选择使用一个策略类。

  • 导致产生众多策略类和对象
    策略模式导致成产生众多策略类和对象,可通过亨元模式弥补该不足。


4 什么地方使用策略模式

   策略模式的优点决定了其适用的场景,反过来其缺点即是其不适用的场景。策略模式适用场景:


  • 一个需要多种算法处理的场景,并需要动态选择其中一个算法

  • 一个有多种相似类的场景,类之间的区别仅仅是行为不同,可考虑使用策略模式使得对象动态选择一个行为

  • 需要屏蔽算法规则的场景,不希望将算法相关数据结构、算法实现过程、算法原理等暴露给用户

  • 重构历史遗留代码,以if-else、switch-case语句实现的,将算法行为和算法实现混合在一起的,或者多种行为混合一起的等维护性差的遗留代码,考虑使用策略模式重构


具体实例:

  • null

5 策略模式实现

实例情况:

  • 抽象策略类Strategy声明具体策略类访问接口AlgorithmInterface
  • 环境角色Context提供算法访问方法ContextInterface
  • 具体策略类ConcreteStrategyAConcreteStrategyBConcreteStrategyB分别实现三个不同行为(算法)具体方法AlgorithmInterface
  • 用户client调用Context方法选择三个策略类行为(算法)

实现过程:

  • 第一步,声明抽象策略类Strategy
/* strategy.h */
#ifndef _STRATEGY_H_
#define _STRATEGY_H_

class Strategy
{
public:
     virtual void AlgorithmInterface() = 0;	/* 抽象接口 */
};
#endif

  • 第二步,声明环境角色类context
/* context.h */
#ifndef _CONTEXT_H_
#define _CONTEXT_H_

#include "strategy.h"

class Context
{
public:
     Context(Strategy *strategy);
     void ContextInterface();
private:
     Strategy *m_strategy;
};
#endif

  • 第三步,环境角色方法实现
/* context.cpp */
#include "context.h"
#include <iostream>

using namespace std;

Context::Context(Strategy *strategy)
{
	m_strategy = strategy;
}

void Context::ContextInterface()
{
	cout << "Call Context::ContextInterface()" << endl;	
	m_strategy->AlgorithmInterface();
}


  • 第四步,声明具体策略类
/* concrete_strategy.h */
#ifndef _CONCRETE_STRATEGY_H_
#define _CONCRETE_STRATEGY_H_

#include "strategy.h"

class ConcreteStrategyA : public Strategy
{
public:
     void AlgorithmInterface();
};

class ConcreteStrategyB : public Strategy
{
public:
     void AlgorithmInterface();
};

class ConcreteStrategyC : public Strategy
{
public:
     void AlgorithmInterface();
};
#endif

  • 第五步,具体策略类方法实现
/* concrete_strategy.cpp */
#include "concrete_strategy.h"
#include <iostream>

using namespace std;

void ConcreteStrategyA::AlgorithmInterface()
{
	/* todo */
    cout<<"Call ConcreteStrategyA::AlgorithmInterface()"<<endl;
}

void ConcreteStrategyB::AlgorithmInterface()
{
	/* todo */
    cout<<"Call ConcreteStrategyB::AlgorithmInterface()"<<endl;
}

void ConcreteStrategyC::AlgorithmInterface()
{
	/* todo */
    cout<<"Call ConcreteStrategyC::AlgorithmInterface()"<<endl;
}

  • 第六步,客户调用具体策略算法
/* client.cpp */
#include "strategy.h"
#include "context.h"
#include "concrete_strategy.h"

int main(int argc, char **arv)
{
	Strategy *strategyA = new ConcreteStrategyA;
	Context *contextA = new Context(strategyA);
	contextA->ContextInterface();
	delete strategyA;
	delete contextA;
	
	Strategy *strategyB = new ConcreteStrategyB;
	Context *contextB = new Context(strategyB);
	contextB->ContextInterface();
	delete strategyB;
	delete contextB;
	
	Strategy *strategyC = new ConcreteStrategyC;
	Context *contextC = new Context(strategyC);
	contextC->ContextInterface();
	delete strategyC;
	delete contextC;
	return 0;
}

执行结果:

acuity@ubuntu:/mnt/hgfs/LSW/STHB/design/strategy$ g++ -o client client.cpp concrete_strategy.cpp context.cpp 
acuity@ubuntu:/mnt/hgfs/LSW/STHB/design/strategy$ ./client
Call Context::ContextInterface()
Call ConcreteStrategyA::AlgorithmInterface()
Call Context::ContextInterface()
Call ConcreteStrategyB::AlgorithmInterface()
Call Context::ContextInterface()
Call ConcreteStrategyC::AlgorithmInterface()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Acuity.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值