设计模式 —— 策略模式

133 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第1天,点击查看活动详情

设计模式 —— 策略模式

如果你读过《三国》,可能会知道一个“锦囊妙计”的故事,当时刘备娶亲,前往东吴,诸葛亮不能陪在主公的身边,因此给了三个锦囊,里面有他写好的计策,给了陪同刘备前去的赵云,并且一再嘱咐每个锦囊应当在什么时候打开,最终刘备抱得美人归,而周郎则是赔了夫人又折兵

由这个故事引出今天的主角——策略模式,那么,二者的关联何在呢?
客官不要急,听我细细道来~

1. 关键词

首先,我们先画下重点,从故事中找出一些关键的词句:
娶亲、三个、锦囊、写好的计策、适当的时机(总结可得)

娶亲:这是我们要做的事情,目的就是这个,刘备要娶了孙家小姐并且平安回来,这便对应了代码具体需要实现的功能,或者说是客户的需求

三个:这是个量词,说明有多个计策、锦囊备选,对应于代码便是多个类或者功能模块

锦囊:包起来的,不打开你看不到,在代码层面代表的就是对于算法的封装

写好的计策:解决问题的办法,代码层面上解决问题的办法不正是一个个算法吗?

适当的时机:我们经常说看情况而定之类的,其实就是需要根据对应条件或者说环境,使用相应的策略解决问题

好了,经过这么一分析,基本上就已经把策略模式的定义整出来了...

总结一下:
对于解决一类问题我们有多种方案,根据具体的场景而定,对这些解决问题的方案进行封装,彼此间相互独立,可以灵活切换

2. 结构分析

image.png

这里给出了策略模式的UML简图,简要的解释一下:
Context在这里代表的是环境,更确切地表述就是你选择某个策略的依据,在你面临具体的问题时做出对应的决策,这需要条件
那么,既然你要做出决策,你的决策与环境间就建立了关联,环境中的条件诱导你做出某种决策,因此提供了stragety成员,代表了持有的关系
Stragety作为一个接口存在,代表的是一种标准和共性,就比如刘备娶亲,它共同的目的就是保证刘备去江东娶到孙家小姐并且平安返回,而具体需要做什么来保证,这便是策略的具体内容了,也是接口实现所需要关注的,下面的三个接口实现类便是做的这件事,当然,策略可以使任意个,只需保证它们的目的一致

3. 代码实现

感觉好像结构捋得差不多了?那就来实践一下

/**
 * 妙计接口
 * @author 诸葛亮
 */
public interface GoodPlan {

    /**
     * 保命
     */
    void saveLife();
}

妙计用来保命,军师已经想清楚了

/**
 * 妙计一: 到江东就打开
 * @author 诸葛亮
 */
public class PlanA implements GoodPlan {

    @Override
    public void saveLife() {
        System.out.println("大肆宣扬,让大家伙都知道,尤其是乔国老和吴国太");
        // 一段时间后
        try {
            Thread.sleep(1000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("效果拔群,良辰吉日,甘露寺成亲,婚礼现场防护get");
    }
}
/**
 * 妙计二:年底打开 
 * @author 诸葛亮
 */
public class PlanB implements GoodPlan {

    @Override
    public void saveLife() {
        System.out.println("告诉主公荆州危机,设法离开");
        try {
            // 思前想后,想到办法
            Thread.sleep(2000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("主公偷偷开溜~~");
    }
}
/**
 * 妙计三:紧急关头打开
 * @author 诸葛亮
 */
public class PlanC implements GoodPlan {

    @Override
    public void saveLife() {
        System.out.println("声情并茂地向孙夫人揭露周瑜的行为,夫人开路");
        try {
            Thread.sleep(500L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("各路援军陆续赶到救驾,顺便刺激下周瑜脆弱的神经~");
    }
}

然后是三条妙计,分别装在三个锦囊中

/**
 * 外界的情况
 */
public class Context {

    private GoodPlan goodPlan;

    public Context(GoodPlan goodPlan) {
        this.goodPlan = goodPlan;
    }

    /**
     * 时机到来,需要保命
     */
    public void opportunityComes() {
        goodPlan.saveLife();
    }
}

看情况而定,就做这件事,等待时机

/**
 * 历史的舞台
 */
public class Stage {

    public static void main(String[] args) {

        Context context;
        // 时机
        System.out.println("到了江东");
        context = new Context(new PlanA());
        context.opportunityComes();

        try {
            Thread.sleep(3000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("年底了");
        context = new Context(new PlanB());
        context.opportunityComes();

        try {
            Thread.sleep(1000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("危急关头");
        context = new Context(new PlanC());
        context.opportunityComes();
    }
}

最终的故事则是在历史的舞台上上演,大致就是这样吧😂

算是策略模式简单的实践吧,如果有什么错误还请多多指正,也欢迎提出建议~~