zoukankan      html  css  js  c++  java
  • 大话设计模式—策略模式

    在策略模式(Strategy Pattern)中,一个类的行为或其算法能够在执行时更改。

    这样的类型的设计模式属于行为型模式。

    大话设计模式中程杰老师给出的定义是这样的:策略模式(Strategy),定义了算法家族,分别封装起来。让它们之间能够互相替换,从模式让算法的变化不会影响到使用算法的用户

    面向对象编程,并非类越多越好,类的划分是为了封装。但分类的基础是抽象,具有同样属性和功能的对象的抽象集合才是类,即区分这些类的仅仅是他们的直接行为;

    一个非常形象的实例就是商场的收银系统。商场收银时怎样促销。用打折还是返利,事实上都是一些算法,打一折和打九折仅仅是形式不同。抽象分析出来。全部的打折算法都是一样的,算法本身仅仅是一种实现促销或打折的策略,重要的是这些算法是随时都可能被替换掉的。这就是变化点。而封装变化点是我们面向对象的一种非常重要的思维方式。

    这里写图片描写叙述

    实例解析

    我们将创建一个定义活动的 Strategy 接口和实现了 Strategy 接口的实体策略类。Context 是一个使用了某种策略的类。
    StrategyPatternDemo,我们的演示类使用 Context 和策略对象来演示 Context 在它所配置或使用的策略改变时的行为变化。类图例如以下:

    这里写图片描写叙述

    策略接口:

    package com.dfcDemo;
    
    public interface Strategy {
    
        public int doOperation(int num1,int num2);
    
    }
    

    四个策略实现类:

    package com.dfcDemo;
    
    public class StrategySubstract implements Strategy{
    
        @Override
        public int doOperation(int num1, int num2) {
            return num1 - num2;
        }
    
    }
    
    package com.dfcDemo;
    
    public class StrategyAdd implements Strategy{
    
        @Override
        public int doOperation(int num1, int num2) {
            return num1 + num2;
        }
    
    }
    
    package com.dfcDemo;
    
    public class StrategyMulpitly implements Strategy{
    
        @Override
        public int doOperation(int num1, int num2) {
            return num1 * num2;
        }
    
    }
    
    package com.dfcDemo;
    
    public class StrategyDivision implements Strategy{
    
        @Override
        public int doOperation(int num1, int num2) {
            //此处注重策略模式的应用,仅仅给出简单实现。不考虑除数为0的情况
            return num1 / num2;
        }
    
    }
    

    使用策略的Context类:

    package com.dfcDemo;
    
    public class Context {
    
        private Strategy strategy;
    
        public Context(Strategy strategy){
            this.strategy = strategy;
        }
    
        public int executeStrategy(int num1,int num2){
            return strategy.doOperation(num1, num2);
        }
    }
    

    測试类:

    package com.dfcDemo;
    
    public class TestStrategyDemo {
    
        public static void main(String[] args) {
    
            Context contextAdd = new Context(new StrategyAdd());
            System.out.println("6 + 3 = " + contextAdd.executeStrategy(6, 3));
    
            Context contextSubstract = new Context(new StrategySubstract());
            System.out.println("6 - 3 = " + contextSubstract.executeStrategy(6, 3));
    
            Context contextMulpitly = new Context(new StrategyMulpitly());
            System.out.println("6 * 3 = " + contextMulpitly.executeStrategy(6, 3));
    
            Context contextDivision = new Context(new StrategyDivision());
            System.out.println("6 / 3 = " + contextDivision.executeStrategy(6, 3));
    
        }
    
    }
    
    执行结果:
    
    6 + 3 = 9
    6 - 3 = 3
    6 * 3 = 18
    6 / 3 = 2

    策略模式是一种定义一系列算法的方法。从概念上来看,全部这些算法完毕的都是同样的工作,仅仅是实现不同,它能够以同样的方式调用全部的算法,降低了各种算法类与使用算法类之间的耦合。Strategy类层次为Context定义了一系列的可供重用的算法和行为。当不同的行为堆砌在一个类中的时候。就非常难避免使用条件语句来推断选择合适的行为。将这些行为封装在一个个独立的Strategy类中,能够在使用这些行为的类中消除条件语句。

    长处:

    1、算法能够自由切换。
    2、避免使用多重条件推断。
    3、扩展性良好。
    4、简化了单元測试。由于每一个算法都有自己的类,能够通过自己的接口单独測试。

    缺点: 1、策略类会增多。 2、全部策略类都须要对外暴露。

    使用场景:

    1、假设在一个系统里面有很多类,它们之间的差别仅在于它们的行为,那么使用策略模式能够动态地让一个对象在很多行为中选择一种行为。

    2、一个系统须要动态地在几种算法中选择一种。
    3、假设一个对象有非常多的行为,假设不用恰当的模式,这些行为就仅仅好使用多重的条件选择语句来实现。

    注意事项:假设一个系统的策略多于四个。就须要考虑使用混合模式,解决策略类膨胀的问题。

    策略模式时用来封装算法的,但在实践中。我们发现能够用它来封装差点儿不论什么类型的规则,仅仅要在分析过程中听到须要在不同一时候间应用不同的业务规则。就能够考虑使用策略模式处理这样的可能发生的变化。

    可是在策略模式中,选择所用详细实现的职责由client对象承担,并转给策略模式使用对象。这本身并没有解除client须要选择推断的压力,解决这一问题的方法是使用策略模式和简单工厂模式结合,选择详细实现的职责也由策略使用类Context来承担。这就最大化的减轻了client的职责。

    策略模式和简单工厂模式结合:

    改造使用策略模式的Context类使事实上现一个简单工厂的功能

    package com.dfcDemo;
    
    //将实例化详细策略的过程由client转移到详细策略使用类ContextFactory中
    public class ContextFactory {
    
        private Strategy strategy;
    
        //注意这里传入的參数是一个表示策略类型的字符串,而不是详细的策略对象
        public ContextFactory(String type){
            switch(type){
            case "add":
              StrategyAdd add = new StrategyAdd();
              strategy = add;
              break;
            case "substract":
              StrategySubstract substract = new StrategySubstract();
              strategy = substract;
              break;
            case "multiply":
              StrategyMulpitly mulpitly = new StrategyMulpitly();
              strategy = mulpitly;
              break;
            case "division":
              StrategyDivision division = new StrategyDivision();
              strategy = division;
              break;
        }
        }
    
        public int executeStrategy(int num1,int num2){
            return strategy.doOperation(num1, num2);
        }
    }
    //測试方法
    public int TestStrategyFactoryDemo(String type) {
    
        ContextFactory contextFactory = new ContextFactory(type);
        return contextFactory.executeStrategy(6, 3);
    
    }

    这样详细策略的使用就与client彻底分离了。

  • 相关阅读:
    关于 Mercury_Lc 说明
    Java 对象和类
    Java int 与 Integer 区别
    Java Number & Math 类
    HTML | CSS | JavaScript 常见错误
    B. Heaters ( Codeforces Round #515 (Div. 3) )
    A. Vova and Train ( Codeforces Round #515 (Div. 3) )
    数据结构实验之排序四:寻找大富翁(SDUT 3401)
    JavaScript 与 Java
    A. The Fair Nut and Elevator (Codeforces Round #526 (Div. 2))
  • 原文地址:https://www.cnblogs.com/wgwyanfs/p/7391483.html
Copyright © 2011-2022 走看看