设计模式——策略模式

作者: 9dfaf364d57f | 来源:发表于2018-04-02 14:23 被阅读51次

前言

设计模式是指导一个程序猿以更好的姿态处理一些问题,而不再像刚学编程的我们,只会使用if-else分支语句,或是使用硬干的骚操作完成需求。不使用设计模式,一来是代码逻辑会越来越晦涩难懂(到了某天你会发现自己也没办法看清楚所有逻辑),二来是代码维护成本越来越高(你的加班时间会越来越长),三来是可以装bility。基于这么多的好处,小盆友和大家一起讨论和分享下设计模式,让自己不再是一个坐在电脑前敲代码的码农。

讲个小故事——“半百老人迎娶貌美孙小妹”

讲模式前,老套路,先讲个小故事。



今天借用下三国的一个经典场景,孙权想夺回荆州,于是想将孙小妹“嫁”给刘备,让刘备来吴迎娶小妹。但嫁给刘备是假,软禁刘备是真。于是小亮让赵云随行,并且给了三个锦囊,让其在危机时刻打开,化险为夷。三个锦囊是找乔国老帮帮忙,找吴国太帮帮忙,找孙小妹帮帮忙。故事在《三国演义》中写的很精彩,我在这就不讲书了,有兴趣的猿们,可以自行翻阅,增加自己一点bi气。
现在用猿的视线分析下刚才的场景,赵云只是一个使用锦囊的用户,随身携带了三个算法(锦囊),具体是什么算法,赵云不知道,只知道遇到第一个困难就用第一个,第二个困难就用第二个,第三个困难就用第三个。
今天就不尬码了,我直接按模式来,先看看策略模式的经典类图


策略模式

从类图中我们可以知道,策略模式中主要是三个类:

  1. Context类:用于装入计谋,类似于我们场景中的锦囊
  2. Strategy接口:是所有计谋的接口。
  3. ConcreteStrategy类:具体的计谋,类似于我们场景中三个具体计谋

映射后我们的类图如下,三个计谋继承于计谋接口,锦囊中持有一个计谋,让用户打开。


image.png

编码时刻

先来看IStrategy接口,申明了一个通用的接口,作为计谋的接口方法

public interface IStrategy {

    public void operate();

}

接下来看三个计谋,比较简单,各自实现自己的计谋步骤

public class QiaoGuoLaoStrategy implements IStrategy {
    @Override
    public void operate() {
        System.out.println("找乔国老。。。。");
    }
}
public class SunFuRenEnemy implements IStrategy {
    @Override
    public void operate() {
        System.out.println("让孙小妹断后。。");
    }
}
public class WuGuoTaiStrategy implements IStrategy {
    @Override
    public void operate() {
     System.out.println("找吴国太帮忙。。");
    }
}

然后锦囊类,可以将计谋装入,需要使用时就调用operate方法,开启计谋

public class SilkBag {

    private IStrategy mStrategy;

    public SilkBag(IStrategy strategy) {
        this.mStrategy = strategy;
    }

    public void operate(){
        this.mStrategy.operate();
    }

}

最后登场的是赵子龙,每次需要就从list中取出一个计谋然后实施,完美解决此场景。

public class ZhaoZiLong {
    public static void main(String[] args) {
        List<SilkBag> silkBagList = new ArrayList<>();
        silkBagList.add(new SilkBag(new QiaoGuoLaoStrategy()));
        silkBagList.add(new SilkBag(new WuGuoTaiStrategy()));
        silkBagList.add(new SilkBag(new SunFuRenEnemy()));

        int i = 1;
        for (SilkBag silkBag : silkBagList) {
            System.out.println("赵子龙第" + (i++) + "次遇困难,使用锦囊:");
            silkBag.operate();
        }
    }
}

策略模式缺点

上面的代码真的完美么?不完美,因为使用的用户需要知道具体的计谋类。当计谋多的时候,用户就需要知道相应多的类,违背了迪米特法则(最少知识原则),所以我们可以进行相应的封装,这里我使用工厂模式进行简单的封装。
使用简单工厂模式,用于生产锦囊,其实这样更加符合场景的描述,赵云在使用锦囊的时候其实并不知道哪条计谋是第一个,那条计谋是第二个。对于他来说,他只知道我是按顺序来使用,所以传进工厂说我需要第一个计谋,工厂就给了第一个,至于里面是乔国老还是孙小妹的,这个他就不需要关心了。

public class SilkBagFactory {

    public static SilkBag getStrategy(int i){
        SilkBag silkBag = null;
        switch (i){
            case 1:
                silkBag = new SilkBag(new QiaoGuoLaoStrategy());
                break;
            case 2:
                silkBag = new SilkBag(new WuGuoTaiStrategy());
                break;
            case 3:
                silkBag = new SilkBag(new SunFuRenEnemy());
                break;
        }
        return silkBag;
    }

}

再来看看如何调用,代码更加简洁了。

public class ZhaoZiLong {

    public static void main(String[] args) {
//        List<SilkBag> silkBagList = new ArrayList<>();
//        silkBagList.add(new SilkBag(new QiaoGuoLaoStrategy()));
//        silkBagList.add(new SilkBag(new WuGuoTaiStrategy()));
//        silkBagList.add(new SilkBag(new SunFuRenEnemy()));
//
//        int i = 1;
//        for (SilkBag silkBag : silkBagList) {
//            System.out.println("赵子龙第" + (i++) + "次遇困难,使用锦囊:");
//            silkBag.operate();
//        }

        for (int i = 1; i <= 3; ++i) {
            System.out.println("赵子龙第" + i + "次遇困难,使用锦囊:");
            SilkBagFactory.getStrategy(i).operate();
        }

    }

}

写在最后

本篇文章没有长篇大论的讲理论,因为这不是我的风格,更多的是通过前后的代码对比和一些编码时微妙的变化入手,如果这篇文章对你有所启发请给个“❤️”鼓励下吧。

代码地址:https://github.com/zincPower/JDesign

相关文章

网友评论

    本文标题:设计模式——策略模式

    本文链接:https://www.haomeiwen.com/subject/sybthftx.html