Java中,状态模式和策略模式的区别

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java中,状态模式和策略模式的区别相关的知识,希望对你有一定的参考价值。

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

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

(1)相似之处

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

这是专为经典的VM问题而设计的状态模式UML类图。可以看出,VM的状态是个接口,表示不同状态的具体实现。每一个状态都持有Context的引用,用来管理由Context触发的行为导致的状态转移。

这是专为实现排序功能而设计的策略模式UML类图。因为存在很多排序算法,该模式让Client在排序时选择适当的算法。事实上,Java的集合框架就使用这个模式,实现了用来排序的Collections.sort()方法。不同的是,不允许Client选择排序算法,而是让传递Comparator或Comparable接口的实例来指定比较策略。

(2)不同之处

策略模式封装了一组相关算法,允许Client在运行时使用可互换的行为;状态模式帮助一个类在不同的状态显示不同的行为。

状态模式封装了对象的状态,而策略模式封装算法或策略。因为状态是跟对象密切相关的,不能被重用;而通过从Context中分离出策略或算法,可以重用。

在状态模式中,每个状态通过持有Context的引用,来实现状态转移;但是每个策略都不持有Context的引用,只是被Context使用。

策略实现可以作为参数传递给使用的对象,例如Collections.sort(),参数包含一个Comparator策略。另一方面,状态是Context对象自己的一部分,随着时间的推移,Context对象从一个状态转移到另一个状态。

虽然都符合OCP原则,策略模式也符合SRP原则(单一职责原则),因为每个策略都封装自己的算法,且不依赖其他策略。一个策略的改变,并不会导致其他策略的变化。

另一个理论上的不同:策略模式定义了对象“怎么做”的部分。例如,排序对象怎么对数据排序。状态模式定义了对象“是什么”和“什么时候做”的部分。例如,对象处于什么状态,什么时候处在某个特定的状态。

状态模式中很好的定义了状态转移的次序;而策略模式并无此需要:Client可以自由的选择任何策略。

一些常见的策略模式的例子是封装算法,例如排序算法,加密算法或者压缩算法。如果看到代码需要使用不同类型的相关算法,那么考虑使用策略模式吧。而识别何时使用状态模式是很简单的:如果需要管理状态和状态转移,但不想使用大量嵌套的条件语句,那么就是了。

最后但最重要的一个不同之处是,策略的改变由Client完成;而状态的改变,由Context或状态自己。

参考技术A 你好
Java开发者,要想恰当的使用状态模式和策略模式,必须清楚的理解它们之间的区别。虽然状态模式和策略模式拥有相似的结构,虽然它们都基于SOLID设计原则中的O(开闭原则),但是,它们的意图是完全不同的。
策略模式通过封装一组相关算法,为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对象被创建时就被提供的。
这是专为经典的VM问题而设计的状态模式UML类图。你可以看出,VM的状态是个接口,它有表示不同状态的具体实现。每一个状态都持有Context的引用,用它来管理由Context触发的行为导致的状态转移。
这是专为实现排序功能而设计的策略模式UML类图。因为存在很多排序算法,该模式让Client在排序时选择适当的算法。事实上,Java的集合框架就使用这个模式,实现了用来排序的Collections.sort()方法。不同的是,它不允许Client选择排序算法,而是让它传递Comparator或Comparable接口的实例来指定比较策略。
让我们来看看它们之间更多的相似之处:
添加新的状态或策略都很容易,而且不需要修改使用它们的Context对象。
它们都让你的代码符合OCP原则。在状态模式和策略模式中,Context对象对修改是关闭的,添加新的状态或策略,都不需要修改Context。
正如状态模式中的Context会有初始状态一样,策略模式同样有默认策略。
状态模式以不同的状态封装不同的行为,而策略模式以不同的策略封装不同的行为。
它们都依赖子类去实现相关行为。
不同之处
现在我们知道,状态模式和策略模式的结构是相似的,但它们的意图不同。让我们重温一下它们的主要不同之处:
策略模式封装了一组相关算法,它允许Client在运行时使用可互换的行为;状态模式帮助一个类在不同的状态显示不同的行为。
状态模式封装了对象的状态,而策略模式封装算法或策略。因为状态是跟对象密切相关的,它不能被重用;而通过从Context中分离出策略或算法,我们可以重用它们。
在状态模式中,每个状态通过持有Context的引用,来实现状态转移;但是每个策略都不持有Context的引用,它们只是被Context使用。
策略实现可以作为参数传递给使用它的对象,例如Collections.sort(),它的参数包含一个Comparator策略。另一方面,状态是Context对象自己的一部分,随着时间的推移,Context对象从一个状态转移到另一个状态。
虽然它们都符合OCP原则,策略模式也符合SRP原则(单一职责原则),因为每个策略都封装自己的算法,且不依赖其他策略。一个策略的改变,并不会导致其他策略的变化。
另一个理论上的不同:策略模式定义了对象“怎么做”的部分。例如,排序对象怎么对数据排序。状态模式定义了对象“是什么”和“什么时候做”的部分。例如,对象处于什么状态,什么时候处在某个特定的状态。
状态模式中很好的定义了状态转移的次序;而策略模式并无此需要:Client可以自由的选择任何策略。
一些常见的策略模式的例子是封装算法,例如排序算法,加密算法或者压缩算法。如果你看到你的代码需要使用不同类型的相关算法,那么考虑使用策略模式吧。而识别何时使用状态模式是很简单的:如果你需要管理状态和状态转移,但不想使用大量嵌套的条件语句,那么就是它了。
最后但最重要的一个不同之处是,策略的改变由Client完成;而状态的改变,由Context或状态自己。

本文链接地址: Java中,状态模式和策略模式的区别

希望可以帮到你

祝你学习愉快

本回答被提问者和网友采纳

状态模式和策略模式的区别

【中文标题】状态模式和策略模式的区别【英文标题】:Difference between State pattern and Strategy pattern 【发布时间】:2013-08-09 15:51:04 【问题描述】:

查看 GoF 模式,我发现 State 和 Stategy 模式之间的相似之处相当惊人。 两者都交换了多态类来修改行为。其他人也发现了吗?

具体有什么区别?

【问题讨论】:

***.com/questions/1658192/… 的副本 【参考方案1】:

状态和策略模式在某种意义上是相似的,它们都将行为封装在单独的对象中,并使用组合来委托组合的对象来实现行为,并且它们都提供了通过改变对象来动态改变行为的灵活性。在运行时组合对象。但是有一些关键的区别:

    在状态模式中,客户端对状态对象一无所知。状态更改对客户端透明地发生。客户端只是在上下文中调用方法,上下文监督自己的状态。因为客户端不知道状态更改,所以每次由于状态更改而导致行为发生更改时,对客户端来说似乎上下文是从不同的类实例化的。作为模式的官方定义,该对象似乎会更改其类。该模式是围绕一系列明确定义的状态转换构建的。改变状态是模式存在的关键。

    尽管策略模式提供了通过动态更改组合策略对象来更改行为的灵活性,但大多数情况下已经为每个上下文设置了适当的策略对象。即,即使该模式提供了一种动态更改组合策略对象的方法,但对它的需求并不大。即使必须这样做,也是客户进行更改。客户端将调用上下文的 setter 方法并传递新的策略对象。因此,行为变化对客户端不透明,由客户端发起和控制。该模式不鼓励像状态模式那样进行一系列明确定义的行为更改。客户端知道策略对象,并且通常会在创建策略对象时在上下文中设置适当的策略对象。客户端控制上下文使用的策略对象,但在状态模式中,客户端对上下文使用的状态对象一无所知

    更多信息请参考以下链接http://myrandomsparks.blogspot.in/2012/05/strategy-vs-state-pattern.html

【讨论】:

“因此行为变化对‘客户端’不透明,由客户端发起和控制。”我猜这不是“客户”而是“上下文”。 @AnuThomasChandy 在这种情况下是一样的。【参考方案2】:

策略模式决定“如何”执行某些操作,状态模式决定“何时”执行这些操作。

通过使用状态模式,状态持有(上下文)类不再需要知道它是什么状态或类型以及可用的状态或类型。这意味着该类遵循开闭设计原则 (OCP):类对状态/类型的变化是封闭的,但状态/类型对扩展是开放的。

通过使用策略模式,算法使用(上下文)类从如何执行特定任务(--“算法”)的知识中解脱出来。这个案例也创建了对 OCP 的遵守;该课程因有关如何执行此任务的更改而关闭,但设计非常开放,可以添加其他算法来解决此任务

【讨论】:

以上是关于Java中,状态模式和策略模式的区别的主要内容,如果未能解决你的问题,请参考以下文章

状态模式和策略模式的区别

策略和状态模式之间的简化区别

孪生兄弟状态模式与策略模式有什么区别,究竟该如何选择

Java 设计模式之状态学习与掌握

Java 设计模式之状态学习与掌握

Java 设计模式之状态学习与掌握