zoukankan      html  css  js  c++  java
  • 行为型模式:策略模式

    LieBrother原文
    行为型模式:策略模式

    景

    十一大行为型模式之五:策略模式。

    简介

    姓名 :策略模式

    英文名 :Strategy Pattern

    价值观 :集计谋于一身

    个人介绍
    Define a family of algorithms,encapsulate each one,and make them interchangeable.
    定义一组算法,将每个算法都封装起来,并且使它们之间可以互换。
    (来自《设计模式之禅》)

    你要的故事

    先看一张拍得不好看的图片

    洗衣机面板

    每天上完班回到家第一件事情是干啥?有人一进门就躺在沙发上闭目养神、有人一进门躺在沙发上玩手机、有人一进门就陪自己的小宠物玩等等。而我进门第一件事就是洗澡,洗完澡很容易就把一整天的疲惫感给消除掉,然后就可以开始美好的下班时光。现实没那么美好,洗完澡后还要洗衣服,大学手洗了 4 年的衣服,一出来工作,宿舍第一必需品就是洗衣机。细看洗衣机,有很多种洗衣类型,比如:标准、大物、快洗、轻柔。洗衣类型的区别在于洗衣服的过程不一样,洗衣过程包括有浸泡、洗涤、漂洗、脱水,还有洗衣服的时间也不一样。细想可以发现这 4 种洗衣类型其实是洗衣服的 4 种不同的策略,也即是 4 种不同的算法。根据这个思路,我们可以用代码实现它,定义一个接口 WashingStrategy 定义洗衣服类型,而这些类型都有各自的洗衣过程,比如标准洗衣类型就包括浸泡、洗涤、漂洗、脱水,而快洗则只包括洗涤、漂洗、脱水。而我们洗衣服则需要选择某个洗衣类型后,洗衣机就开始工作了。过程如下代码所示。

    public class StrategyTest {                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
    
        public static void main(String[] args) {
            WashingStrategy washingStrategy = new StandardWashingStrategy();
            WashingMachine washingMachine = new WashingMachine(washingStrategy);
            washingMachine.washingClothes();
        }
    
    }
    
    /**
     * 洗衣类型
     */
    interface WashingStrategy {
        void washing();
    }
    
    /**
     * 洗衣机
     */
    class WashingMachine {
        private WashingStrategy washingStrategy;
    
        public WashingMachine(WashingStrategy washingStrategy) {
            this.washingStrategy = washingStrategy;
        }
    
        public void washingClothes() {
            this.washingStrategy.washing();
        }
    }
    
    /**
     * 标准
     */
    class StandardWashingStrategy implements WashingStrategy{
    
        @Override
        public void washing() {
            System.out.println("标准流程:");
            System.out.println("[浸泡] 10 分钟");
            System.out.println("[洗涤] 2 次,每次 15 分钟");
            System.out.println("[漂洗] 1 次,每次 10 分钟");
            System.out.println("[脱水] 5 分钟");
            System.out.println("总共耗时:55 分钟");
        }
    }
    
    /**
     * 快洗
     */
    class QuickWashingStrategy implements WashingStrategy {
    
        @Override
        public void washing() {
            System.out.println("快洗流程:");
            System.out.println("[洗涤] 1 次,每次 10 分钟");
            System.out.println("[漂洗] 1 次,每次 10 分钟");
            System.out.println("[脱水] 5 分钟");
            System.out.println("总共耗时:25 分钟");
        }
    }
    
    /**
     * 大物
     */
    class BigClothesWashingStrategy implements WashingStrategy {
    
        @Override
        public void washing() {
            System.out.println("大物流程:");
            System.out.println("[浸泡] 30 分钟");
            System.out.println("[洗涤] 3 次,每次 15 分钟");
            System.out.println("[漂洗] 2 次,每次 10 分钟");
            System.out.println("[脱水] 5 分钟");
            System.out.println("总共耗时:100 分钟");
        }
    }
    
    /**
     * 轻柔
     */
    class SoftWashingStrategy implements WashingStrategy {
    
        @Override
        public void washing() {
            System.out.println("轻柔流程:");
            System.out.println("[浸泡] 10 分钟");
            System.out.println("[漂洗] 2 次,每次 15 分钟");
            System.out.println("[脱水] 5 分钟");
            System.out.println("总共耗时:45 分钟");
        }
    }
    
    标准流程:
    [浸泡] 10 分钟
    [洗涤] 2 次,每次 15 分钟
    [漂洗] 1 次,每次 10 分钟
    [脱水] 5 分钟
    总共耗时:55 分钟
    

    是不是感觉策略模式很简单呢?上面代码就是完整的策略模式示例,是不是感觉有些问题,这 4 种洗衣类型对象完全暴露给了用户,这也是策略模式的缺点。往往策略模式不会单独使用,会和其他设计模式一起使用,比如和简单工厂模式一起使用就可以解决这个对外暴露对象的问题,看下面代码。

    /**
     * 洗衣类型选择
     */
    class WashingFactory {
    
        public static WashingStrategy getWashingStrategy(String type) {
            if ("Quick".equals(type)) {
                return new QuickWashingStrategy();
            }
            if ("BigClothes".equals(type)) {
                return new BigClothesWashingStrategy();
            }
            if ("Soft".equals(type)) {
                return new SoftWashingStrategy();
            }
            return new StandardWashingStrategy();
        }
    }
    
    public class StrategyTest {
    
        public static void main(String[] args) {
            WashingStrategy washingStrategy2 = WashingFactory.getWashingStrategy("Soft");
            WashingMachine washingMachine2 = new WashingMachine(washingStrategy2);
            washingMachine2.washingClothes();
        }
    }
    
    打印结果:
    轻柔流程:
    [浸泡] 10 分钟
    [漂洗] 2 次,每次 15 分钟
    [脱水] 5 分钟
    总共耗时:45 分钟
    

    代码中使用 WashingFactory 来封装 4 种策略,使得策略没有对外暴露,我们也了解到设计模式之间具有互补的关系,有些时候并不是单独存在的。

    代码:
    Strategy Pattern

    总结

    策略模式是一个很好的封装各种复杂处理的设计模式,让使用者根据自己的选择来选中策略,而不用修改其他代码。当策略太多的时候,可能造成使用方变得复杂、难管理多个策略的问题,利用工厂方法模式可以很好的解决这个难题。这其中也是一个见招拆招的问题,设计模式在真正运用中也是这样子的,遇到问题使用恰当的设计模式去解决问题。

    参考资料:《大话设计模式》、《设计模式之禅》

    推荐阅读:

    公众号之设计模式系列文章

    希望文章对您有所帮助,设计模式系列会持续更新,感兴趣的同学可以关注公众号:LieBrother,第一时间获取文章推送阅读,也可以一起交流,交个朋友。

    公众号

  • 相关阅读:
    重新排列数组
    一维数组的动态和
    aiohttp实现爬虫功能
    python django项目创建及前期准备(使用pycharm)
    vue 使用高德开放平台获取经纬度
    git切换分支时,该分支的修改被带到另一个分支
    vue刻度尺组件
    js将PDF转为base64格式,并在将base64格式PDF回显在页面中
    Linux系统(Centos)安装tomcat和部署Web项目
    linux下安装 tomcat 和配置防火墙开放8080端口
  • 原文地址:https://www.cnblogs.com/liebrother/p/10435127.html
Copyright © 2011-2022 走看看