美文网首页Android知识Android开发经验谈Java学习笔记
还为那些设计模式烦恼吗—策略模式

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

作者: Jenchar | 来源:发表于2016-07-31 00:26 被阅读144次

策略模式

</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>

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

相关文章

网友评论

    本文标题:还为那些设计模式烦恼吗—策略模式

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