「设计模式(一) - 策略模式」

「设计模式(一) - 策略模式」

一、从if-else说起

代码中if-else的出现频率不必多说,几乎的逻辑实现都离不这个组合。但是带来了方便的同时,也带来了多重嵌套代码块。套用重构的一句话,这些都是代码的坏味道。过多的条件判断必然增加了系统不稳定性,同时也给扩展带来了不便因素。当然优化的方式多种多样,策略模式Strategy仅仅只是其中简单的一种。

二、策略模式 Strategy

行为模式的一种,定义了一系列平行的算法,将实现与责任相分离并加以封装,当然各个策略之间是可以相互转化的。由客户端决定使用何种策略,由于策略之间的独立,为系统提供了很好的扩展性。可以理解为相同行为不同实现的组合。

三、组成部分
  • 抽象的策略(Strategy)类:公共的策略接口strategy,派生出不同的实现算法(行为是相同的),当然这个抽象的策略一般是接口,也有情况下是抽象类(具有公共的主体)。

  • 具体实现(Concrete Strategy):策略接口或者策略抽象类的具体实现类。

  • 上下文(Context):分两种情况,一种是客户端本身,另一种情况则是持有策略的引用。

  • 结构图:


    图片来自网络.png
四、简单的代码实现
1.设计一个数据加密的系统

数据加密的方式有很多种,AES、DES、RSA等等。加密的方式多种多样,但是在一个加密的系统中,加密这个行为是同样。而实现这个行为的方法是不同的。加密在这里是策略的抽象。

  • 定义加密策略顶层接口
/**
 * Created by Sai
 * on: 09/01/2022 01:08.
 * Description:策略接口
 */
public interface EncryptionAlgorithm {
    String encrypt(String message);
}
  • 以AES的方式进行加密-策略的具体实现
/**
 * Created by Sai
 * on: 09/01/2022 01:08.
 * Description:
 */
public class AES implements EncryptionAlgorithm {

    @Override
    public String encrypt(String message) {
        System.out.println("Encrypting message using AES");
        return "AES ---> " + " " + message;
    }
}
  • 以DES的方式进行加密
/**
 * Created by Sai
 * on: 09/01/2022 01:08.
 * Description:
 */
public class DES implements EncryptionAlgorithm {

    @Override
    public String encrypt(String message) {
        System.out.println("Encrypting message using DES");
        return "DES --->" + " " + message;
    }
}
  • 以RSA的方式进行加密
/**
 * Created by Sai
 * on: 09/01/2022 01:12.
 * Description:
 */
public class RSA implements EncryptionAlgorithm {

    @Override
    public String encrypt(String message) {
        System.out.println("Encrypting message using RSA");
        return "RSA ---> " + " " + message;
    }
}
  • 客户端持有类用类
/**
 * Created by Sai
 * on: 09/01/2022 01:15.
 * Description:
 */
public class Client {
    private final EncryptionAlgorithm encryptionAlgorithm;

    public Client(EncryptionAlgorithm encryptor) {
        this.encryptionAlgorithm = encryptor;
    }

    public void handleMessage(String message) {
        var encryptedMessage = encryptionAlgorithm.encrypt(message);
        System.out.println(encryptedMessage);
    }
}

这里客户端Client持有了策略对象,通过上下文Context设置关系,具体选择哪种策略是由客户端来作出选择。另一种则是由上下文来决定何种策略,调用顺序上是由差别的,但是影响不大。当然也是根据具体的业务来合理选择。

  • 测试用例
/**
 * Created by Sai
 * on: 09/01/2022 01:17.
 * Description:
 */
public class Demo {
    public static void show() {
        //选择AES进行加密
        var client = new Client(new AES());
        client.handleMessage("send messages...");
    }

    public static void main(String[] args) {
        show();
    }
}
2.一些思考

虽然是个简单的例子,但是也能看出策略模式的一些优缺点,即使现在需要增加一个新的加密算法;那么同样只需要实现顶层策略接口即可(同一行为的不同实现,面向接口的便利)它是易扩展的,但是并不代表着可以无限的增长。在例子中也发现了一个问题,同一时刻只有一个策略被执行,也造成了一定的维护成本。其次,客户端必须了解所有的策略(或者上下文Context),具体选择哪种策略是需要客户端来主动选择的。回想之前的开闭原则,这里其实已经暴露了具体的实现。当然瑕不掩瑜,策略模式是解决多重条件嵌套有效方式之一。

3.没有完美的设计模式

N种策略但同一时刻只有一种被用到了,多少有点浪费,以上述例子为例,其实可以考虑使用责任链模式替换。而且并不会暴露具体的内部实现,那是不是说责任链模式就比策略模式好呢?答案是否定的,考虑到加密方式的繁多性,责任链的链调用深度势必会很深。看,同样是有瑕疵的。没有完美的设计模式(不然也不会出现经典的23种)。但是某种情况下,各种模式的配合可以趋于完美。学习设计模式,个人觉得还是思想的学习吧。

五、开发中的实际问题

最近开发中就遇到了类似的问题,服务端WebSocket下发通知,需要处理这个通知来控制打印机工作,根据Notify Type的不同打印不同的信息文本。而目前已经实现的只有一种type,考虑到type的扩展性,想以策略形式抽象出来。

private void processPrint(PrintMessage printMessage) {
   if (printMessage == null || CheckUtil.isEmpty(printMessage.getPrintType())) {
         return;
   }
   IFetchDataDetail fetchDataDetail;
   if (printMessage.isCondition()) {
       fetchDataDetail = new PrintXXPrintRequest();
      } else {
       fetchDataDetail = new PrintNormalPrintRequest();
   }
   fetchDataDetail.onFetchDataToPrint(printMessage);
}

public interface IFetchDataDetail {
    void onFetchDataToPrint(PrintMessage message);
}

这里的抽象出来的核心操作只有一个,尽管type是不同的,但是都是通过返回的id查询详情并且打印,那么统一的行为就是IFetchDataDetail,只有一个方法void onFetchDataToPrint(PrintMessage message)至于打印何种信息,那就是策略内部的具体实现了。

但它是策略模式吗?其实不是的,与策略模式唯一的区别是没有上下文Context,可以说是退化了的策略模式:退化成简单的面向接口编程,仅仅对多重判断做了整理优化。但接口隔离优点还是有体现的,表面上看没有上下文影响不大。可事实上,客户端的难度增加了,因此还是可以继续优化的。设计的唯一目的,不就是降低客户端的使用复杂度嘛。

六、应该什么时候用
  • 仅仅只是行为实现上的区别-同一行为不同实现。
  • 优化多重条件的嵌套问题。
  • 具体业务场景具体分析,重要的还是抽象思想的理解。
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,270评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,489评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,630评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,906评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,928评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,718评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,442评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,345评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,802评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,984评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,117评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,810评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,462评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,011评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,139评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,377评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,060评论 2 355

推荐阅读更多精彩内容

  • 策略模式(Strategy Pattern)也叫做政策模式(Policy Pattern),是一种行为型模式。 一...
    l只为终点阅读 612评论 1 3
  • 二十三种设计模式 - 策略模式 策略模式简介 模式动机 完成一项任务,往往可以有多种不同的方式,每一种方式称为一个...
    JustTheSame阅读 1,833评论 2 16
  • 概念及定义 概念在完成某一功能时,有时需要根据不同环境采取不同的策略或行为。将这些不同的策略或行为(称为算法)一一...
    maxwellyue阅读 536评论 0 0
  • 策略模式 定义一组算法,将每个算法都封装起来,并且使它们之间可以互换。将共同的行为封装成策略接口,不同策略实现类只...
    AnimoBlog阅读 256评论 0 1
  • 什么是策略模式 策略模式定义了一系列算法,并将每个算法封装起来,使他们可以相互替换,且算法的变化不会影响到使用算法...
    小波同学阅读 254评论 0 1