设计模式之策略模式

一直没有养成写博客的习惯,很早就打算通过设计模式来开始博客之旅,后面因为上半年找工作对并发知识缺乏。就学了一阵子以并发相关内容开始写博客了,现在才写了几篇,之后会继续完善。现在在阅读《Head First设计模式》,刚好博客记录下学习过程。都知道设计模式在OO编程中很重要,理解和在实际中运用完全不是同一回事,但是在运用之前我们起码的先学会不是吗?

策略模式定义:定义了算法族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。

使用场景:针对同一类型问题的多种处理方式,仅仅是具体行为有差别时,策略模式能够很好地应对变化;

下面我们将通过一个烹饪鸡的例子来更好的理解(至于为什么是烹饪鸡,仅仅只是喜欢吃鸡肉);

首先我们定义一个Person接口类

这个person有很多技能(吃饭睡觉打豆豆),我们不关注,本场景下我们用到的只有一个cookieChicken(烹饪鸡肉)

//人物类
public interface Person {
    //烹饪鸡肉
    void cookingChicken();
}

接下来本篇博客主角陈师傅登场

//陈师傅
public class MasterChen implements Person {
    @Override
    public void cookingChicken() {
        System.out.println("辣子鸡");
    }
}

陈师傅(也喜欢吃鸡肉),尤其是辣子鸡,所以他烹饪鸡的做法,第一种就学的辣子鸡

好,接下来我们把鸡肉交给陈师傅

public static void main(String[] args) {
        Person masterChen = new MasterChen();
        masterChen.cookingChicken();
    }

陈师傅也不负众望,做出了美味的辣子鸡

辣子鸡

天天吃一种菜总是会腻的,尽管喜欢吃,陈师傅依稀记得在重庆旅游的时候,吃过一次正宗的重庆鸡公煲,味道很是美味,话不多话,就是干。陈师傅开始学重庆鸡公煲的做法,不久后出师。

现在我们构造的陈师傅应该怎么样适应变化呢?恩  一开始肯定都是这么想的,我们改造下

//人物类
public interface Person {
    //烹饪鸡肉
    void cookingChicken(String type);
}

人物类中烹饪鸡肉我们增加一个type区分不同的做法

//陈师傅
public class MasterChen implements Person {
    @Override
    public void cookingChicken(String type) {
        if(type.equals("辣子鸡")){
            System.out.println("辣子鸡");
        }else if(type.equals("重庆鸡公煲")){
            System.out.println("重庆鸡公煲");
        }

    }
}

现在的陈师傅可以通过type,来用不同的烹饪方式烹饪鸡肉

public static void main(String[] args) {
        Person masterChen = new MasterChen();
        masterChen.cookingChicken("辣子鸡");
        masterChen.cookingChicken("重庆鸡公煲");
    }
辣子鸡
重庆鸡公煲

恩,这样我们的目的的确达到了,偶然的一次机会,陈师傅到广州沟通学习,并学会了白切鸡的做法。

为了适应变化,我们又要修改我们构造的陈师傅。不过在修改之前,我们思考一个问题,每次陈师傅新学一种烹饪鸡肉的做法,我们就要修改我们构造的陈师傅,这是不是不合适呢?在OO编程中,我们一直主张对扩展开发,对修改关闭。我们此刻的做法就违背这个原则。在实际生产中我们应该也是尽量做到新增功能不影响原有的功能。

此刻,策略模式隆重登场,在这个场景中,不断变化的是烹饪鸡的做法,我们可以把其看做策略模型中的算法抽离出来。以后增加算法都不影响原有的功能。

这里我们先把类之间的关系图放出来(烹饪鸡肉行为和人物分离然后组合进来)

 

设计模式之策略模式_第1张图片

 

人物类改造

public abstract class Person {
    //烹饪鸡肉的行为
    CookChicken cookChicken = null;
    //烹饪鸡肉
    abstract void  cookingChicken();

    public void setCookChicken(CookChicken oneCookChicken){
        cookChicken =oneCookChicken;
    }
}

这里我们将人物类由接口改成了抽象类,将烹饪鸡肉这一做法抽离成行为的方式(面对接口编程不一定是指完全面对Interface编程,关键在于多态。利用多态,程序可以针对超类型编程,某些场景下抽象类比接口更合适)

烹饪鸡肉行为类

public interface CookChicken {
    void cooking();
}

同时,针对辣子鸡,和白切鸡我们定义了两个实现类

辣子鸡:

public class SpicyChicken implements CookChicken {
    @Override
    public void cooking() {
        System.out.println("辣子鸡");
    }
}

白切鸡:

public class WhiteCutChicken implements CookChicken {
    @Override
    public void cooking() {
        System.out.println("白切鸡");
    }
}

重庆鸡公煲:

public class ChongqingChicken implements CookChicken {
    @Override
    public void cooking() {
        System.out.println("重庆鸡公煲");
    }
}

 

最后就是经过改造的陈师傅,此刻的陈师傅能够灵活运用多种烹饪鸡肉的做法

public class MasterChen extends Person {

    public MasterChen() {
        cookChicken = new SpicyChicken();
    }

    @Override
    public void cookingChicken() {
        //默认用陈师傅最熟悉的辣子鸡来实例化
        cookChicken.cooking();
    }
}

接下来到了关键的做菜过程了

public class Test {
    public static void main(String[] args) {
        Person masterChen = new MasterChen();
        masterChen.cookingChicken();
        masterChen.setCookChicken(new ChongqingChicken());
        masterChen.cookingChicken();
        masterChen.setCookChicken(new WhiteCutChicken());
        masterChen.cookingChicken();

    }
}

 

辣子鸡
重庆鸡公煲
白切鸡

经过我们的改造,我们能在运行时通过setCookChicken在陈师傅工作期间,动态用不同的烹饪手法,做出不同的鸡肉(辣子鸡、重庆鸡公煲、白切鸡)。今后即时陈师傅各种深造,学习更多地烹饪鸡肉的做法。我们也只需要实现更多地烹饪行为实现类,无需对陈师傅进行各种改造。

这就是策略模式,通过将某些相同系列算法抽离程序,在组合进去,使得系统更具有弹性。

最后我们在回顾一次策略模式的定义,是不是理解更深刻了呢

策略模式定义:定义了算法族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。

 

参考资料:《Head First 设计模式》

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(设计模式,策略模式)