策略模式与状态模式之间有什么区别?我查阅了很多文章,但是仍然不能清楚地区分它们的不同。
请问有人能用通俗易懂的语言来解释它们之间的区别吗?
策略模式与状态模式之间有什么区别?我查阅了很多文章,但是仍然不能清楚地区分它们的不同。
请问有人能用通俗易懂的语言来解释它们之间的区别吗?
实际上,这两种模式在实践中非常相似,它们之间的定义差异往往取决于你问谁。一些流行的选择包括:
“经典”的实现方式将为列表中的每个项目匹配状态或策略,但您可能会遇到混合使用两者的情况。无论特定的实现是更加“状态”还是更加“策略”,最终都是主观问题。
getStatus()
方法,该方法将根据对象的状态返回不同的状态值,但方法的调用者不必针对每个潜在的状态编写不同的代码。这两种模式的区别在于它们解决不同的问题:
然而,实现这两种模式的构建方式非常相似;两种模式都是组合和委托的例子。
对它们优点的一些观察:
使用 State 模式可以使持有状态(上下文)的类从需要知道自己处于哪个状态或类型以及哪些状态或类型可用的知识中解脱出来。这意味着该类符合开闭原则(OCP):对于状态/类型的更改,类本身是关闭的,但是状态/类型是开放的,可以扩展。
使用 Strategy 模式可以使使用算法(上下文)的类从需要知道如何执行某个任务的知识中解脱出来。这也符合 OCP;该类对于如何执行此任务的更改是关闭的,但是设计非常开放,可以添加其他算法来解决此任务。
这可能还会提高上下文类对单一职责原则(SRP)的遵守度。此外,算法很容易被其他类重用。
适用策略模式的最后一种情况与称为用多态替换条件表达式的重构相关。
总结:状态和策略解决非常不同的问题。如果您的问题不能用有限状态机建模,那么状态模式可能不合适。如果您的问题不涉及封装复杂算法的变体,则不适用策略。
状态(State)具有以下UML类结构:
策略具有以下UML类结构:
摘要:就静态结构而言,这两种模式大多相同。事实上,诸如this one的模式检测工具认为“[...]这些模式的结构是相同的,禁止了它们在自动处理过程中(例如,不参考概念信息)的区分。”策略模式涉及将算法的实现从托管类中移出,放入一个单独的类中。这意味着宿主类不需要自己提供每个算法的实现,这很可能导致代码不清晰。
排序算法通常被用作示例,因为它们都做同样的事情(排序)。如果每种不同的排序算法都被放入其自己的类中,那么客户端就可以轻松地选择要使用的算法,而模式提供了一种简便的方法来访问它。
状态模式涉及在对象状态改变时更改对象的行为。这意味着宿主类不必为对象可能处于的所有不同状态提供行为的实现。宿主类通常封装一个类,该类在给定状态下提供所需的功能,并在状态更改时切换到另一个类。
策略模式代表着执行相同的开始和结束结果,但使用不同方法在内部“执行”某些操作的对象。在这个意义上,它们类似于表示动词的实现。另一方面,状态模式使用“是”某些东西的对象 - 操作的状态。虽然它们也可以表示对该数据的操作,但更类似于名词的表示而不是动词,并且专为状态机设计。
策略模式用于当你有多个针对特定任务的算法时,客户端决定在运行时使用哪个实际实现。
维基百科上的UML图表格策略模式文章:
关键特征:
请参考此文章以获取更多信息和真实世界示例:
状态模式允许一个对象在其内部状态发生变化时改变其行为。
维基百科上的UML图表格状态模式文章:
如果我们需要根据对象的状态更改其行为,我们可以在对象中使用一个状态变量,并使用if-else条件块根据状态执行不同的操作。 状态模式用于通过上下文和状态实现提供一种系统化和松耦合的方式来实现此目标。更多细节请参考journaldev文章。
与sourcemaking和journaldev文章的关键区别:
策略模式:策略是固定的,通常由几个步骤组成。(排序只构成了一个步骤,因此是一个非常糟糕的例子,因为它太简单了,无法理解此模式的目的)。
策略中的“主”程序调用一些抽象方法。例如,“进入房间策略”,“主方法”是goThroughDoor(),看起来像这样:approachDoor(),如果(locked())openLock(); openDoor(); enterRoom(); turn(); closeDoor(); 如果(wasLocked())lockDoor()
现在,这个通用的从一个房间到另一个房间通过可能被锁的门移动的“算法”的子类可以实现算法的步骤。
换句话说,对策略进行子类化不会改变基本算法,只会改变个别步骤。
上述内容是模板方法模式。现在将属于同一步骤的步骤(解锁/锁定和打开/关闭)放入它们自己的实现对象中并委托给它们。例如,具有钥匙的锁和具有代码卡的锁是两种锁。从策略向“步骤”对象进行委派。现在,您就有了一个策略模式。
状态模式是完全不同的。
您有一个包装对象和被包装对象。被包装的对象是“状态”。状态对象只能通过其包装器访问。现在,您可以随时更改被包装的对象,因此包装器似乎更改了其状态,甚至更改了其“类”或类型。
例如,您有一个登录服务。它接受用户名和密码。它只有一个方法:logon(String userName,String passwdHash)。它不决定是否接受登录,而是将决策委托给状态对象。该状态对象通常只检查用户/密码组合是否有效并执行登录。但现在,您可以通过仅允许特权用户登录(例如,在维护时间期间)或通过不允许任何人登录来将“Checker”的更换。这意味着“checker”表示系统的“登录状态”。
最重要的区别是:一旦选择了策略,就要坚持到完成为止。这意味着你调用其“主方法”,只要该方法在运行,就不会更改策略。另一方面,在状态模式情况下,在系统运行时,您可以根据需要任意更改状态。
layman's language中,Strategy模式没有状态或所有状态都相同。 它只有不同的执行任务方式,就像不同的医生用不同的方式治疗同一个患者的同一种疾病。
在State模式中,主观上存在状态,例如患者的当前状态(例如高温或低温),基于此决定下一步的行动(药品处方)。 一个状态可以导致另一个状态,因此存在状态到状态的依赖关系(在技术上称为组合)。
如果我们从技术上理解它,根据两者的代码比较,我们可能会失去情境的主观性,因为两者看起来非常相似。