设计模式——策略模式

作者: 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