zoukankan      html  css  js  c++  java
  • Java设计模式之行为型模式(策略模式)

    策略模式(Strategy)

    1、概述

    ①定义

    《JAVA与模式》一书中是这样定义策略模式的:

    策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。

    策略模式的策略是什么意思?有朋友可能会疑惑:在Java中,“策略”和“方法”有什么区别?首先,策略与方法含义相近,都指应对问题的办法手段。策略比方法更加宏观,更加正式,策略更加强调地位作用,可以看作是一种“升级版”的方法。在Java中,方法就是形如show()这样的,它是被包含在类或接口中的,只是类的成员(成员变量、成员方法)。在Java中,策略不在是方法那么简单。策略虽然与方法相近,但一个策略并不是一个类的成员单位,而是一个类(或接口)为单位。我们暂且可以把Java中的策略看作“策略类”(Strategy class)。

    ②结构

    首先我们来看看策略模式的结构图:

    这里写图片描述

    • Strategic为策略性接口,接口中定义了一个operateStrategy()方法,方法体内期望用于实现策略性接口的算法
    • Strategy1、Strategy2、Strategy3为三个独立的策略类,都实现Strategic接口的operateStrategy()方法

    可见,在策略模式中,每一个策略的单位是类,而不是方法。算法被封装在策略类的内部。

    · 解答疑惑

    为何策略模式需要先定义一个抽象的策略接口?

    答案:我们知道,在存在多个处于统一平台,拥有同等地位的类这一场景中,使这些类共同实现或继承同一个接口或父类,能够有效提高代码的扩展性和可维护性、健壮性。试想,假设现在有一个Context类,Context类中需要使用某种策略,若这些策略类没有实现共同的接口或继承共同的父类,当有策略类增加的需求时,我们不但要写定义新的策略类的代码,还要在Context类中依次添加策略类,这样就违背了开闭原则;若这些策略类实现了共同的接口或继承共同的父类,当Context需要使用某种策略时,就可以通过一个方法,这个方法以接口类或者父类类型的引用来充当参数,充分利用了Java中多态的特性,且若有增多策略类的需求时,仅需写定义新的策略类的代码,而无需修改Context中的代码。

    3、实例分析

    利用策略模式实现四个策略类,分别为:Plus、Minus、Multiple、Divide,由这四个策略类构成几个基本的计算器。每一个策略类中封装了对应的算法。

    UML图:

    这里写图片描述

    代码:

    /**
     * @author Hanlin Wang
     */
    
    public class StrategyMode {
        public static void main(String[] args) {
            //选择不同的策略Strategy:加、减、乘、除。
            Plus plus = new Plus();
            double res = plus.calculate("1+1+2+5");
            System.out.println(res);
    
            Minus minus = new Minus();
            double res2 = minus.calculate("9-6-1");
            System.out.println(res2);
    
            Multiple multiple = new Multiple();
            double res3 = multiple.calculate("4*8*2");
            System.out.println(res3);
    
            Divide divide = new Divide();
            double res4 = divide.calculate("64/4/2");
            System.out.println(res4);
        }
    }
    
    //方法模板
    interface Calculator{
        double calculate(String exp);
    }
    
    //实现模板
    class Plus implements Calculator{
        public double calculate(String exp) {
            String[] seg = exp.split("\+");
            double res = 0.0;
            for (int i = 0; i < seg.length; i++) {
                res += Double.parseDouble(seg[i]);
            }
            return res; 
        }
    }
    
    class Minus implements Calculator{
        public double calculate(String exp) {
            String[] seg = exp.split("\-");
            double res = Double.parseDouble(seg[0]);
            for (int i = 1; i < seg.length; i++) {
                res -= Double.parseDouble(seg[i]);
            }
            return res; 
        }
    }
    
    class Multiple implements Calculator{
        public double calculate(String exp) {
            String[] seg = exp.split("\*");
            double res = 1.0;
            for (int i = 0; i < seg.length; i++) {
                res *= Double.parseDouble(seg[i]);
            }
            return res; 
        }
    }
    
    class Divide implements Calculator{
        public double calculate(String exp) {
            String[] seg = exp.split("\/");
            double res = Double.parseDouble(seg[0]);
            for (int i = 1; i < seg.length; i++) {
                res /= Double.parseDouble(seg[i]);
            }
            return res; 
        }
    }
  • 相关阅读:
    013.ES6 -对象字面量增强型写法
    012. ES6
    011. ES6 语法
    10. 9. Vue 计算属性的setter和getter 以及 计算属性的缓存讲解
    4. Spring MVC 数据响应方式
    3. SpringMVC 组件解析
    9. Vue 计算属性
    【洛谷 2984】给巧克力
    【洛谷 1821】捉迷藏 Hide and Seek
    【洛谷 1821】银牛派对Silver Cow Party
  • 原文地址:https://www.cnblogs.com/wanxi/p/6476228.html
Copyright © 2011-2022 走看看