• 策略模式学习


    策略模式

    定义

    策略模式(StrategyPattern):定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化,也称为政策模式(Policy)。

    策略模式是一种对象行为型模式。

    模式结构

    • Context: 环境类
    • Strategy: 抽象策略类
    • ConcreteStrategy: 具体策略类

    图解

    时序图

    时序图

    代码实现

    Stratege.js

    /**
     * 排序策略父类
     */
    class Stratege {
      sort() {
        throw new Error('顶级父类的sort不能直接调用')
      }
    }
    /** 
     * 冒泡排序
    */
    class BubbleStratege extends Stratege {
      sort([...arr]) {
        for (let i = 0; i < arr.length; i++) {
          for(let j = 0; j < arr.length; j++) {
            if (arr[j] > arr[j + 1]) {
              let temp = arr[j];
              arr[j] = arr[j + 1];
              arr[j + 1] = temp;
            }
          }
        }
        return arr;
      }
    }
    /** 
     * 选择排序
    */
    class ChoosenStratege extends Stratege {
      sort([...arr]) {
        for (let i = 0; i < arr.length; i++) {
          for(let j = i + 1; j < arr.length; j++) {
            if (arr[i] > arr[j]) {
              let temp = arr[i];
              arr[i] = arr[j];
              arr[j] = temp;
            }
          }
        }
        return arr;
      }
    }
    /**
     * 插入排序
     */
    class InsertStatege extends Stratege {
      sort([...arr]) {
        for(let i = 1; i < arr.length; i++) {
          let value = arr[i];
          let j = i - 1;
          while(j >= 0 && arr[j] > value) {
            arr[j + 1] = arr[j];
            j --;
          }
          arr[j + 1] = value;
        }
        return arr;
      }
    }
    
    module.exports = {
      BubbleStratege,
      ChoosenStratege,
      InsertStatege,
    }
    

    Context.js

    /**
     * 上下文
      */
    module.exports = class Context {
      constructor(arr) {
        this.arr = arr;
      }
      setSort(stratege) {
        return stratege.sort(this.arr);
      }
    }
    
    

    main.js

    const Context = require('./Context');
    const {
      BubbleStratege,
      ChoosenStratege,
      InsertStatege,
    } = require('./Stratege')
    function main() {
      //生成随机数组
      let arr = Array.from({length: Math.ceil(Math.random() * 20)}, _ => Math.floor(Math.random() * 100));
      console.log(arr, '原始数组')
      //上下文
      const context = new Context(arr);
      //冒泡排序策略
      let arr1 = context.setSort(new BubbleStratege());
      console.log(arr1, '应用冒泡策略')
      //选择排序策略
      let arr2 = context.setSort(new ChoosenStratege());
      console.log(arr2, '应用选择策略')
      //插入排序策略
      let arr3 = context.setSort(new InsertStatege());
      console.log(arr3, '应用插入策略')
    
    }
    main();
    

    运行结果

    
    0|main  | [ 33, 69, 59, 69, 25, 95, 66, 14, 27, 61, 43, 22, 38 ] '原始数组'
    0|main  | [ 14, 22, 25, 27, 33, 38, 43, 59, 61, 66, 69, 69, 95 ] '应用冒泡策略'
    0|main  | [ 14, 22, 25, 27, 33, 38, 43, 59, 61, 66, 69, 69, 95 ] '应用选择策略'
    0|main  | [ 14, 22, 25, 27, 33, 38, 43, 59, 61, 66, 69, 69, 95 ] '应用插入策略'
    0|main  | [ 64, 31, 69, 31 ] '原始数组'
    0|main  | [ 31, 31, 64, 69 ] '应用冒泡策略'
    0|main  | [ 31, 31, 64, 69 ] '应用选择策略'
    0|main  | [ 31, 31, 64, 69 ] '应用插入策略'
    0|main  | [ 59, 59, 85, 48, 0, 72, 95, 9, 22, 2, 27, 18, 17, 23, 59 ] '原始数组'
    0|main  | [ 0, 2, 9, 17, 18, 22, 23, 27, 48, 59, 59, 59, 72, 85, 95 ] '应用冒泡策略'
    0|main  | [ 0, 2, 9, 17, 18, 22, 23, 27, 48, 59, 59, 59, 72, 85, 95 ] '应用选择策略'
    0|main  | [ 0, 2, 9, 17, 18, 22, 23, 27, 48, 59, 59, 59, 72, 85, 95 ] '应用插入策略'
    0|main  | [ 24, 19, 56, 43, 28, 17, 24, 25, 91, 16, 18, 98, 27, 87, 95, 47, 49, 75 ] '原始数组'
    0|main  | [ 16, 17, 18, 19, 24, 24, 25, 27, 28, 43, 47, 49, 56, 75, 87, 91, 95, 98 ] '应用冒泡策略'
    0|main  | [ 16, 17, 18, 19, 24, 24, 25, 27, 28, 43, 47, 49, 56, 75, 87, 91, 95, 98 ] '应用选择策略'
    0|main  | [ 16, 17, 18, 19, 24, 24, 25, 27, 28, 43, 47, 49, 56, 75, 87, 91, 95, 98 ] '应用插入策略'
    0|main  | [ 34, 50, 27 ] '原始数组'
    0|main  | [ 27, 34, 50 ] '应用冒泡策略'
    0|main  | [ 27, 34, 50 ] '应用选择策略'
    0|main  | [ 27, 34, 50 ] '应用插入策略'
    
    

    模式分析

    • 策略模式是一个比较容易理解和使用的设计模式,策略模式是对算法的封装,它把算法的责任和算法本身分割开,委派给不同的对象管理。策略模式通常把一个系列的算法封装到一系列的策略类里面,作为一个抽象策略类的子类。用一句话来说,就是“准备一组算法,并将每一个算法封装起来,使得它们可以互换”。
    • 在策略模式中,应当由客户端自己决定在什么情况下使用什么具体策略角色
    • 策略模式仅仅封装算法,提供新算法插入到已有系统中,以及老算法从系统中“退休”的方便,策略模式并不决定在何时使用何种算法,算法的选择由客户端来决定。这在一定程度上提高了系统的灵活性,但是客户端需要理解所有具体策略类之间的区别,以便选择合适的算法,这也是策略模式的缺点之一,在一定程度上增加了客户端的使用难度。

    优点

    • 策略模式提供了对“开闭原则”的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为。
    • 策略模式提供了管理相关的算法族的办法。
    • 策略模式提供了可以替换继承关系的办法。
    • 使用策略模式可以避免使用多重条件转移语句。

    缺点

    • 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
    • 策略模式将造成产生很多策略类,可以通过使用享元模式在一定程度上减少对象的数量。

    总结

    • 在策略模式中定义了一系列算法,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化,也称为政策模式。策略模式是一种对象行为型模式。
    • 策略模式包含三个角色:环境类在解决某个问题时可以采用多种策略,在环境类中维护一个对抽象策略类的引用实例;抽象策略类为所支持的算法声明了抽象方法,是所有策略类的父类;具体策略类实现了在抽象策略类中定义的算法。
    • 策略模式是对算法的封装,它把算法的责任和算法本身分割开,委派给不同的对象管理。策略模式通常把一个系列的算法封装到一系列的策略类里面,作为一个抽象策略类的子类。
    • 策略模式主要优点在于对“开闭原则”的完美支持,在不修改原有系统的基础上可以更换算法或者增加新的算法,它很好地管理算法族,提高了代码的复用性,是一种替换继承,避免多重条件转移语句的实现方式;其缺点在于客户端必须知道所有的策略类,并理解其区别,同时在一定程度上增加了系统中类的个数,可能会存在很多策略类。
    • 策略模式适用情况包括:在一个系统里面有许多类,它们之间的区别仅在于它们的行为,使用策略模式可以动态地让一个对象在许多行为中选择一种行为;一个系统需要动态地在几种算法中选择一种;避免使用难以维护的多重条件选择语句;希望在具体策略类中封装算法和与相关的数据结构。
  • 相关阅读:
    分析一个文本文件(英文文章)中各个词出现的频率,并且把频率最高的10个词打印出来
    求一个数组中的最大整数
    一个统计文本文件中各个英文单词出现频率的问题,并且输出频率最高的10个词
    Python学习一:基础语法
    Spring学习之二
    Spring学习之装配Bean
    Spring学习一
    缓存之ehcache
    解决axios传递参数后台无法接收问题
    服务端解决跨域问题
  • 原文地址:https://www.cnblogs.com/pandapeter/p/11070156.html
Copyright © 2020-2023  润新知