zoukankan      html  css  js  c++  java
  • Strategy策略设计模式

    1、策略模式和状态模式的区别和联系(本部分转载自:http://letscoding.cn/java%E4%B8%AD%EF%BC%8C%E7%8A%B6%E6%80%81%E6%A8%A1%E5%BC%8F%E5%92%8C%E7%AD%96%E7%95%A5%E6%A8%A1%E5%BC%8F%E7%9A%84%E5%8C%BA%E5%88%AB/)

    策略模式通过封装一组相关算法,为Client提供运行时的灵活性。Client可以在运行时,选择任一算法,而不改变使用算法的Context。一些流行的策略模式的例子是写那些使用算法的代码,例如加密算法、压缩算法、排序算法。另一方面,状态模式允许对象,在不同的状态拥有不同的行为。因为现实世界中的对象通常都是有状态的,所以它们在不同状态,行为也不一样。例如,VM(自动售货机)只在hasCoin状态才给你吐商品;你不投币,它是不会吐的。现在你可以清楚的看出它们的不同之处了:它们的意图是不同的。状态模式帮助对象管理状态,而策略模式允许Client选择不同的行为。

    另一个不那么容易能看出来的区别是:是谁促使了行为的改变。策略模式中,是Client提供了不同的策略给Context;状态模式中,状态转移由Context或State自己管理。另外,如果你在State中管理状态转移,那么它必须持有Context的引用。例如,在VM的例子中,State对象需要调用VM的setState()方法去改变它的状态。另一方面,Strategy从不持有Context的引用,是Client把所选择的Strategy传递给Context。由于状态模式和策略模式的区别,是流行的Java设计原则类面试题之一,我们将会在本文探讨在Java中,状态模式和策略模式的异同,这可以加深你对它们的理解。

    相似之处

    如果你看看状态模式和策略模式的UML图,就会发现它们的结构非常相似。使用State对象改变自己行为的对象被称为Context对象;相似的,使用Strategy对象改变自己行为的对象叫Context对象。记住,Client和Context打交道。在状态模式中,Context把方法调用委托给当前的状态对象,而在策略模式中,Context使用的Strategy对象,是被当做参数传递过来的,或在Context对象被创建时就被提供的。

    让我们来看看它们之间更多的相似之处:

    1. 添加新的状态或策略都很容易,而且不需要修改使用它们的Context对象。
    2. 它们都让你的代码符合OCP原则。在状态模式和策略模式中,Context对象对修改是关闭的,添加新的状态或策略,都不需要修改Context。
    3. 正如状态模式中的Context会有初始状态一样,策略模式同样有默认策略。
    4. 状态模式以不同的状态封装不同的行为,而策略模式以不同的策略封装不同的行为。
    5. 它们都依赖子类去实现相关行为。

    不同之处

    现在我们知道,状态模式和策略模式的结构是相似的,但它们的意图不同。让我们重温一下它们的主要不同之处:

    1. 策略模式封装了一组相关算法,它允许Client在运行时使用可互换的行为;状态模式帮助一个类在不同的状态显示不同的行为。
    2. 状态模式封装了对象的状态,而策略模式封装算法或策略。因为状态是跟对象密切相关的,它不能被重用;而通过从Context中分离出策略或算法,我们可以重用它们。
    3. 在状态模式中,每个状态通过持有Context的引用,来实现状态转移;但是每个策略都不持有Context的引用,它们只是被Context使用。
    4. 策略实现可以作为参数传递给使用它的对象,例如Collections.sort(),它的参数包含一个Comparator策略。另一方面,状态是Context对象自己的一部分,随着时间的推移,Context对象从一个状态转移到另一个状态。
    5. 虽然它们都符合OCP原则,策略模式也符合SRP原则(单一职责原则),因为每个策略都封装自己的算法,且不依赖其他策略。一个策略的改变,并不会导致其他策略的变化。
    6. 另一个理论上的不同:策略模式定义了对象“怎么做”的部分。例如,排序对象怎么对数据排序。状态模式定义了对象“是什么”和“什么时候做”的部分。例如,对象处于什么状态,什么时候处在某个特定的状态。
    7. 状态模式中很好的定义了状态转移的次序;而策略模式并无此需要:Client可以自由的选择任何策略。
    8. 一些常见的策略模式的例子是封装算法,例如排序算法,加密算法或者压缩算法。如果你看到你的代码需要使用不同类型的相关算法,那么考虑使用策略模式吧。而识别何时使用状态模式是很简单的:如果你需要管理状态和状态转移,但不想使用大量嵌套的条件语句,那么就是它了。
    9. 最后但最重要的一个不同之处是,策略的改变由Client完成;而状态的改变,由Context或状态自己。

    本段译自:Difference between State and Strategy Design Pattern in Java

    2、URL图下载地址(astah/jude):http://pan.baidu.com/s/1hqy0c88

    3、示例

    公共策略规范接口

    1 package com.xinye.test.strategy;
    2 /**
    3  * 策略通用接口
    4  * @author xinye
    5  *
    6  */
    7 public interface IStrategy {
    8     public void strategy();
    9 }

    默认策略

     1 package com.xinye.test.strategy;
     2 /**
     3  * 默认Strategy
     4  * @author xinye
     5  *
     6  */
     7 public class NormalStrategy implements IStrategy {
     8 
     9     @Override
    10     public void strategy() {
    11         System.out.println(getClass().getSimpleName() + " strategy()");
    12     }
    13 
    14 }

    第一种策略

    package com.xinye.test.strategy;
    /**
     * 第一种Strategy
     * @author xinye
     *
     */
    public class FirstStrategy implements IStrategy {
    
        @Override
        public void strategy() {
            System.out.println(getClass().getSimpleName() + " strategy()");
        }
    
    }

    第二种策略

     1 package com.xinye.test.strategy;
     2 /**
     3  * 第二种Strategy
     4  * @author xinye
     5  *
     6  */
     7 public class SecondStrategy implements IStrategy {
     8 
     9     @Override
    10     public void strategy() {
    11         System.out.println(getClass().getSimpleName() + " strategy()");
    12     }
    13 
    14 }

    策略Context

     1 package com.xinye.test.strategy;
     2 /**
     3  * 策略模式Context
     4  * @author xinye
     5  *
     6  */
     7 public class Context {
     8     
     9     private IStrategy strategy = new NormalStrategy();
    10     /**
    11      * 需要客户端把策略传递过来
    12      * @param s
    13      */
    14     public void exec(IStrategy s){
    15         strategy = s;
    16         strategy.strategy();
    17     }
    18 }

    客户端代码

    package com.xinye.test.strategy;
    /**
     * 客户端代码
     * @author xinye
     *
     */
    public class Client {
        public static void main(String[] args) {
            
            Context context = new Context();
            // 传递给Context特定的策略
            context.exec(new NormalStrategy());
            // 传递给Context特定的策略
            context.exec(new FirstStrategy());
            // 传递给Context特定的策略
            context.exec(new SecondStrategy());
        }
    }

    执行结果
    NormalStrategy strategy()
    FirstStrategy strategy()
    SecondStrategy strategy()

  • 相关阅读:
    oracle 更改账户名密码
    mongodb 分片副本集搭建
    爬虫目录
    centos MySQL安装与卸载
    ANACONDA 安装
    chrome 安装
    linux pycharm 安装 idea
    linux 基本命令
    高数18讲 之极限与连续
    高数18讲 之基础知识
  • 原文地址:https://www.cnblogs.com/xinye/p/3909401.html
Copyright © 2011-2022 走看看