设计模式详解:Strategy(策略模式)

Strategy 策略模式

设计模式学习:概述

意图

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

Strategy模式将算法独立于程序流程之外,降低了算法与程序主流程之间的耦合度。

  1. 将算法硬编入程序主流程段(和程序主流程写在一起),会导致程序难以维护。日后再添加新的算法时,也不利于扩展。
  2. 并且,通常我们只想用一部分算法来支持我们的程序,比如提供的99个算法我们只用到2-3个,那么全部编写在一起会造成内存的大量浪费。当然这只是次要问题,主要要解决的,还是降低程序耦合度。

从稳定-变化的角度来分析的话,使用Strategy模式的程序段,算法本身涉及到增删和变化,但算法段之外的流程保持稳定

代码案例

enum class Sins
{
    
    
    MURDER, STEAL, ROBBERY, DEFRAUD
}

void judge(Sins sin)
{
    
    
    //判罪前的通用流程
    ...
    
    //处理算法
	if(sin == MURDER)  {
    
    ...}
    else if(sin == STEAL) {
    
    ...}
    else if(sin == ROBBERY) {
    
    ...}
    else if(sin == DEFRAUD) {
    
    ...}
        
    //判罪后的通用流程
    ...
}

如上所示,这个例子是一个判罪的程序,“算法” 即针对不同的罪行进行相应的处理(判10年,20年,无期之类的,这只是一个示例,因此省去了大部分细节)。

在这个程序段中,为罪行指定刑罚之前和之后的流程是稳定的,比如,判罪前要搜集罪证啊,检察官提起公诉啊,判罪后要登记在案,罪犯可能会上诉啊之类的。而针对罪行的判定是不稳定的,经常会提出一些修正案,增删或变更一些条款。

考虑这种情况,现在我们需要增加一种算法(也就是增加一种罪名),需要做什么呢?我们需要在ENUM中增加罪名,并且在Judge函数中增加相应的处理代码段。显然,代码的复用性并不好,每次对算法的改变都需要重新编译Judge函数。

从设计原则的角度来讲,这种写法违背了开放封闭原则(OCP)(详情可在文章开头 设计模式学习:概述 中了解)。降低了可扩展性。并且,有可能带来debug的问题:每次对算法的改变都有可能在judge函数内部造成Bug。

那么,现在我们用strategy模式改写一下:

class SinStrategy
{
    
    
    virtual void dealSin() = 0;
    virtual ~SinStrategy(){
    
    };//C++中基类的析构函数要写成虚的!这里提醒大家。
}

class MurderStrategy : public SinStrategy
{
    
    
    //override
    void dealSin() {
    
    ...}
}

class StealStrategy : public SinStrategy
{
    
    
    //override
    void dealSin() {
    
    ...}
}

class RobberyStrategy : public SinStrategy
{
    
    
    //override
    void dealSin() {
    
    ...}
}

void judge(SinStrategy* sin)
{
    
    
    //判罪前的通用流程
    ...
    
    //处理算法,动态绑定
	sin -> dealSin();
        
    //判罪后的通用流程
    ...
}

如上,SinStrategy类作为抽象基类,定义了一个虚函数dealSin,这个函数就是我们要封装的算法。之后的每种罪行只需要重写这一个函数就可以了

而在judge函数中,我们采用动态绑定的方式。程序不知道到底是那种罪名,只需要按规定的流程走完即可。关于SinStrategy具体指向那种子类,就不是我们这个函数操心的问题了。

可以这样调用Judge函数

judge(new StealStrategry());
judge(new MurderStrategry());
judge(new RobberyStrategry());

就实现了对不同罪行的分开处理,而处理罪行的算法也成功的和流程代码段解耦,实现了松耦合

解释

在strategy模式中,我们把一个特定的算法看作一个对象,因此就可以对它应用多态的思想。

可以这样简单的理解:只要在程序中看到if-else语句或switch语句,就要思考这里需不需要应用Strategy模式——Strategy模式相当于将if-else, switch-case中的模块封装到一个个对象中。至于要不要用Strategy替换If-else/switch,取决于你自己的判断。

Strategy模式也是一个十分常见的设计模式,本质思想和TemPlate Method类似,都是为了遵循开放封闭原则,对某些代码段进行封装,只是对象不同罢了。

总结

设计模式 Strategy(策略模式)
稳定点: 程序的整体运行框架
变化点: 子算法
效果: 使得可以独立于主程序增删修改算法
特点: 封装算法,重写子过程

在这里插入图片描述

​ 2020.1.26 转载请标明出处

猜你喜欢

转载自blog.csdn.net/natrick/article/details/113174673
今日推荐