还为那些设计模式烦恼吗—策略模式

策略模式

</br>

前言

很多人在阅读第三方框架(例如Retrofit)的时候,不太懂或者比较吃力,是因为我们缺少一些写代码的思维,看代码的设计的模式,今天,小菜我说下对策略模式的理解
</br>


介绍

  • 专业说法:定义了一系列的算法,并将每个算法封装起来,而且使它们还可以相互替换,策略模式让算法独立于使用它的客户而独立变化
  • 例子说法:假设,今天,我要为舍友煮一道菜,小菜我买了一块猪肉,但是,舍友开心的时候,是喜欢吃红烧肉,则我要做红烧肉;难过的时候,是喜欢吃焖猪肉,则我要做焖猪肉:
    1.难过(策略)->做红烧肉(算法)
    2.开心(策略)->做焖猪肉(算法)
    </br>

改善前的代码

/**
 * Created by Jenchar on 2016/7/30.
 */
public class Meat {
    public static final String HAPPY="开心";
    public static final String SAD="难过";
    public static final String REDMEAT="红烧肉";
    public static final String BRAISEMEAT="焖猪肉";

    public static void main(String[] args) {
        Meat meat=new Meat();
        meat.chooseFood(SAD,BRAISEMEAT);
    }
    private void chooseFood(String fellings,String type) {
        if(fellings.equals(HAPPY)){
            codeRedMeat(type);
        }else{
            cookBraiseMeat(type);
        }
    }

    private void cookBraiseMeat(String meat) {
        System.out.println("他"+HAPPY+"的时候,"+"我要为他煮"+meat);
    }

    private void codeRedMeat(String meat) {
        System.out.println("他"+SAD+"的时候,"+"我要为他煮"+meat);
    }
}

输出结果:
他难过的时候,我要为他煮红烧肉
分析:

Meat类很明显的问题是并不是单一职责(简单来说,就是一个类只有一种功能),首先它承担了做红烧肉和做焖猪肉的职责,另一个问题就是通过if-else的形式来判断做哪一种。小菜想,当我舍友他发神经病,兴奋的时候,会喜欢吃炸猪肉呢,那么我就需要在Meat类中增加一个方法去做炸猪肉,并且要在 chooseFood(String fellings,String type)方法里又增加一个判断,代码如下:
</br>

/**
 * Created by Jenchar on 2016/7/30.
 */
public class Meat {
    public static final String HAPPY="开心";
    public static final String SAD="难过";
    public static final String REDMEAT="红烧肉";
    public static final String BRAISEMEAT="焖猪肉";
    /**
     * 增加的
     */
    public static final String  EXCITED="兴奋";
    public static final String  FLYINGMEAT="炸猪肉";

    public static void main(String[] args) {
        Meat meat=new Meat();
        meat.chooseFood(EXCITED,FLYINGMEAT);

    }
    private void chooseFood(String fellings,String type) {
        if(fellings.equals(HAPPY)){
            codeRedMeat(type);
        }else if(fellings.equals(SAD)){
            cookBraiseMeat(type);
            /**
             * 增加的
             */
        }else if(fellings.equals(EXCITED)){
            cookFlyingMeat(type);
        }
    }

    /**
     *增加的
     */
    private void cookFlyingMeat(String type) {
        System.out.println("他"+EXCITED+"的时候,"+"我要为他煮"+type);
    }

    private void cookBraiseMeat(String meat) {
        System.out.println("他"+HAPPY+"的时候,"+"我要为他煮"+meat);
    }

    private void codeRedMeat(String meat) {
        System.out.println("他"+SAD+"的时候,"+"我要为他煮"+meat);
    }
}
输出结果:
他兴奋的时候,我要为他煮炸猪肉

再分析:

看看 chooseFood(String fellings,String type)这个方法,现在代码是不是很乱了,各种if-else语句缠绕在其中?当小菜的舍友,因为精神分裂,又想吃另外一种,那么,我又要在chooseFood增加if-else。当if-else语句多了,就会很容易看错,写错,而且,代码臃肿,小的项目,小的类虽然过得去,但是到了大的项目,必然会很乱,难以维护。所以,因这种情况 ,小菜我开始引进了一种设计模式,“策略模式”
</br>


改善后的代码

首先小菜我需要定义一个抽象的做肉接口,命名CookStrategy,代码如下:

/**
 * 做肉的接品
 */
public interface CookStrategy {
    /**
     * 根据舍友的情感来做肉
     * @param feelings
     */
    void cook(String feelings);
}

接着对于做红烧肉还是焖猪肉,小菜我觉得应该都有一个独立的做肉策略类,这些类都实现上面说的CookStrategy接口,代码如下:
CookRedMeat.java:

/**
 * 做红烧肉的类
 */
public class CookRedMeat implements CookStrategy{
    public static final String REDMEAT="红烧肉";
    /**
     * 开始做他喜欢的红烧肉
     * @param feelings
     */
    @Override
    public void cook(String feelings) {
        System.out.println("他"+feelings+"的时候,"+"我要为他煮"+REDMEAT);
    }
}

CookBraiseMeat.java:

/**
 * 做焖肉的类
 */
public class CookBraiseMeat implements CookStrategy {
    public static final String BRAISEMEAT="焖猪肉";
    @Override
     /**
     * 开始做他喜欢的焖猪肉
     * @param feelings
     */
    public void cook(String feelings) {
          System.out.println("他"+feelings+"的时候,"+"我要为他煮"+BRAISEMEAT);
    }
}

最后,我们再创建一个的Meat类。

public class Meat {
    public static final String HAPPY="开心";
    public static final String SAD="难过";
    /**
     * 持有CookStrategy对象
     */
    private CookStrategy mCookStrategy;
    public static void main(String[] args) {
        Meat meat=new Meat();
        meat.setCookStrategy(new CookBraiseMeat());
        meat.cookFood(SAD);
    }

    /**
     * 把子类的引用赋值到mCookStrategy,就可以调用子类的方法。
     * @param cookStrategy
     */
    private void setCookStrategy(CookStrategy cookStrategy) {
        mCookStrategy=cookStrategy;
    }
    private void cookFood(String feelings){
        mCookStrategy.cook(feelings);
    }

}
最后分析

通过改善前后的代码,可以看出:

  • 前者:通过if-else解决问题,代码臃肿,逻辑复杂,难以升级与维护,没有结构可言
  • 后者:通过建立接口,将不同的策略构建成一个具体的策略实现 ,通过不同的策略实现算法替换,从而更好地增加扩展性,直观性。
    </br>

结论与使用场景

  • 针对同一类型的问题,多种处理,仅仅是具体为行有差别(做红烧肉,做焖猪肉)
  • 出现同一抽象类有多个子类,虽然使用if-else或者switch-case来选择子类的(根据舍友的心情来做肉)
  • 需要安全地封装多种同一类型的操作时(做红烧肉,做焖猪肉这些操作时)
    </br>

喜欢我的朋友,可以与我一起讨论问题,我也是学习者,希望与大学一起学习。

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

推荐阅读更多精彩内容

  • 1 场景问题# 1.1 报价管理## 向客户报价,对于销售部门的人来讲,这是一个非常重大、非常复杂的问题,对不同的...
    七寸知架构阅读 5,011评论 9 60
  • 1 场景问题 1.1 报价管理 向客户报价,对于销售部门的人来讲,这是一个非常重大、非常复杂的问题,对不同的客户要...
    4e70992f13e7阅读 3,068评论 2 16
  • ¥开启¥ 【iAPP实现进入界面执行逐一显】 〖2017-08-25 15:22:14〗 《//首先开一个线程,因...
    小菜c阅读 6,344评论 0 17
  • 工厂模式类似于现实生活中的工厂可以产生大量相似的商品,去做同样的事情,实现同样的效果;这时候需要使用工厂模式。简单...
    舟渔行舟阅读 7,715评论 2 17
  • 目录 本文的结构如下: 引言 什么是策略模式 模式的结构 典型代码 代码示例 策略模式和模板方法模式的区别 优点和...
    w1992wishes阅读 839评论 1 7