战略设计模式和州设计模式有什么区别?

Chi*_*ser 207 state design-patterns strategy-pattern

战略设计模式和州设计模式之间有什么区别?我在网上经历了不少文章,但无法清楚地看出差异.

有人可以解释外行人的条款差异吗?

小智 128

老实说,这两种模式在实践中非常相似,它们之间的定义差异往往取决于你问的对象.一些流行的选择是:

  • States存储对包含它们的上下文对象的引用.策略没有.
  • 允许状态替换自己(IE:将上下文对象的状态改为其他东西),而策略则不然.
  • 策略作为参数传递给上下文对象,而状态由上下文对象本身创建.
  • 策略只处理单个特定任务,而状态为上下文对象提供的所有(或大多数)提供底层实现.

对于列表中的每个项目,"经典"实现将匹配状态或策略,但是您确实会遇到混合了两者的混合.一个特定的国家是更多的国家还是战略-Y最终是一个主观问题.

  • 如果你把GoF算作流行的选择之一,他们会不同意国家必然是由上下文创建的(可以由客户创建并传递到上下文中,就像使用Strategy一样). (5认同)

Yis*_*hai 99

  • 战略模式实际上是关于具有不同的实现,完成(基本上)同样的事情,这样的策略需要一个实现可以取代其他.例如,您可能在策略模式中使用不同的排序算法.对象的调用者不会根据使用的策略而改变,但无论策略如何,目标都是相同的(对集合进行排序).
  • 模式是这样做基于状态不同的事情,而留下容纳从每一个可能的状态的负担减轻调用者.因此,例如,您可能有一个 getStatus()方法将根据对象的状态返回不同的状态,但方法的调用者不必以不同的方式编码以考虑每个潜在的状态.

  • @Noor,是的,但在我现在能够想到的任何战略模式中,这将是一个前期决定,不会在中间发生变化. (4认同)
  • 但战略格局中的战略是谁改变的呢? (2认同)
  • 我遇到了同样的问题,状态或策略,我认为几句话的区别是,状态,行为是自动确定的,策略,行为是由调用者确定的。 (2认同)

Ulf*_*edt 82

区别在于他们解决了不同的问题:

  • 模式与交易什么(州或类型)的对象是(上) -它封装了状态相关的行为,而
  • 战略格局与涉及如何对象执行特定的任务-它封装了一个算法.

然而,实现这些不同目标的结构非常相似; 两种模式都是具有授权的组合的例子.


对其优势的一些观察:

通过使用状态模式的国有控股(上下文)类是从知识松了一口气什么状态或键入它是什么状态或类型可用.这意味着该类遵循开放式封闭式设计原则(OCP):对于所有状态/类型的更改,类是关闭的,但状态/类型对扩展是开放的.

通过使用策略模式,算法使用(上下文)类从如何执行某个任务( - "算法")的知识中解脱出来.这种情况也会导致对OCP的遵守; 该类因关于如何执行此任务的更改而关闭,但该设计对于添加其他算法以解决此任务非常开放.
这也可能改善上下文类对单一责任原则(SRP)的遵守.此外,该算法变得易于被其他类重用.


Fuh*_*tor 40

有人可以用非专业人的说法解释一下吗?

设计模式并不是真正的"门外汉"概念,但我会尽量让它变得清晰.任何设计模式都可以考虑三个方面:

  1. 模式解决的问题;
  2. 模式的静态结构(类图);
  3. 模式的动态(序列图).

让我们比较国家和战略.

模式解决的问题

状态用于两种情况之一[GoF book p.306]:

  • 对象的行为取决于其状态,并且必须根据该状态在运行时更改其行为.
  • 操作具有依赖于对象状态的大型多部分条件语句.此状态通常由一个或多个枚举常量表示.通常,几个操作将包含相同的条件结构.State模式将条件的每个分支放在一个单独的类中.这使您可以将对象的状态视为一个对象,它可以独立于其他对象而变化.

如果要确保状态模式确实存在问题,则应该能够使用有限状态机对对象的状态进行建模.你可以在这里找到一个应用的例子.

每个状态转换都是State接口中的一个方法.这意味着对于设计,在应用此模式之前,您必须非常确定状态转换.否则,如果添加或删除转换,则需要更改接口和实现它的所有类.

我个人没有发现这种模式有用.您总是可以使用查找表来实现有限状态机(它不是OO方式,但它运行良好).

策略用于以下[GoF book p.316]:

  • 许多相关类只在他们的行为上有所不同.策略提供了一种使用多种行为之一配置类的方法.
  • 你需要不同的算法变体.例如,您可以定义反映不同空间/时间权衡的算法.当这些变体被实现为算法的类层次结构时,可以使用策略[HO87].
  • 算法使用客户端不应该知道的数据.使用策略模式可避免暴露复杂的特定于算法的数据结构.
  • 一个类定义了许多行为,这些行为在其操作中显示为多个条件语句.而不是很多条件,将相关的条件分支移动到自己的Strategy类中.

应用策略的最后一个案例与一个名为Replace conditional with polymorphism的重构有关.

总结:国家和战略解决了截然不同的问题.如果您的问题无法使用有限状态机建模,则可能的状态模式不合适.如果您的问题不是封装复杂算法的变体,那么策略不适用.

图案的静态结构

State具有以下UML类结构:

PlantUML状态模式的类图

策略具有以下UML类结构:

PlantUML策略模式的类图

总结:就静态结构而言,这两种模式大多相同.事实上,像这样的模式检测工具认为"模式的结构是相同的,禁止通过自动过程区分它们(例如,不参考概念信息). "

但是,如果ConcreteStates决定自己的状态转换(参见上图中的" 可能确定 "关联),则可能存在重大差异.这导致具体状态之间的耦合.例如(参见下一节),状态A确定转换到状态B.如果Context类决定转换到下一个具体状态,那么这些依赖关系就会消失.

动态的模式

如上面的问题部分所述,State暗示行为在运行时会根据对象的某些状态而更改.因此,正如有限状态机的关系所讨论的那样,应用状态转换的概念.[GoF]提到过渡可以在ConcreteState子类中定义,也可以在集中位置(例如基于表的位置)定义.

让我们假设一个简单的有限状态机:

PlantUML状态转换图有两个状态和一个转换

假设子类决定状态转换(通过返回下一个状态对象),动态看起来像这样:

PlantUML状态转换的序列图

为了展示战略的动态,借用一个真实的例子是有用的.

用于策略转换的PlantUML序列图

简介:每个模式都使用多态调用来根据上下文执行某些操作.在状态模式中,多态调用(转换)通常会导致下一个状态发生变化.在策略模式中,多态调用通常不会改变上下文(例如,通过信用卡支付一次并不意味着您下次将通过PayPal付款).同样,状态模式的动态由其相应的fininte状态机决定,对我来说,这对于纠正这种模式的应用是必不可少的.


Rya*_*ars 25

策略模式涉及从托管类移动算法的实现并将其放在单独的类中.这意味着主机类不需要提供每个算法本身的实现,这很可能导致不洁的代码.

排序算法通常用作示例,因为它们都做同样的事情(排序).如果将每个不同的排序算法放入其自己的类中,则客户端可以轻松选择要使用的算法,并且该模式提供了一种访问它的简单方法.

状态模式涉及在对象状态改变时改变对象的行为.这意味着主机类没有为它可以处于的所有不同状态提供行为的实现.主机类通常封装一个类,该类提供给定状态所需的功能,并切换到另一个类当国家改变.


zzz*_*eek 14

策略表示"做"某事的对象,具有相同的开始和结束结果,但内部使用不同的方法.从这个意义上讲,它们类似于表示动词的实现.状态模式OTOH使用"是"某些东西的对象 - 操作的状态.虽然它们也可以表示对该数据的操作,但它们更类似于名词的表示而不是动词,并且是针对状态机而定制的.


Mur*_*han 13

考虑处理客户呼叫的IVR(交互式语音应答)系统.您可能希望对其进行编程以处理客户:

  • 工作日
  • 假期

要处理这种情况,您可以使用状态模式.

  • 假期:IVR只是回答说" 只能在上午9点到下午5点之间的工作日打电话 ".
  • 工作日:通过将客户与客户服务主管联系起来.

将客户与支持主管联系起来的过程本身可以使用策略模式来实现,其中基于以下任一方式挑选高管:

  • Round Robin
  • 最近最少使用
  • 其他基于优先级的算法

策略模式决定" 如何 "执行某些操作,状态模式决定" 何时 "执行它们.


Ang*_*ere 11

战略:战略是固定的,通常包括几个步骤.(排序只构成一步,因此是一个非常糟糕的例子,因为它太过于原始,无法理解这种模式的目的).策略中的"主要"例程是调用一些抽象方法.例如"Enter Room Strategy","main-method"是goThroughDoor(),它看起来像:approachDoor(),if(locked())openLock(); 开门(); enterRoom(); 转(); 关门(); if(wasLocked())lockDoor();

现在,通过可能锁定的门从一个房间移动到另一个房间的这种通用"算法"的子类可以实现算法的步骤.

换句话说,对策略进行子类化不会改变基本算法,只会改变单个步骤.

上面是模板方法模式.现在将属于一起的步骤(解锁/锁定和打开/关闭)放入它们自己的实现对象中并委托给它们.例如,带钥匙的锁和带代码卡的锁是两种锁.从策略委派给"Step"对象.现在你有了一个战略模式.

状态模式是完全不同的.

你有一个包装对象和包装对象.包裹的是"状态".只能通过其包装器访问状态对象.现在你可以随时更改包装对象,因此包装器似乎改变了它的状态,甚至是它的"类"或类型.

例如,您有登录服务.它接受用户名和密码.它只有一个方法:logon(String userName,String passwdHash).它不是决定是否接受登录,而是将决策委托给状态对象.该状态对象通常只检查用户/传递组合是否有效并执行登录.但是现在你可以用一个只允许特权用户登录的"Checker"(例如在maintanace时间)或者不允许任何人登录的用户.这意味着"检查器"表示系统的"登录状态".

最重要的区别是:当你选择了一个策略时,你会坚持使用它,直到完成它为止.这意味着你称之为"主要方法",只要那个正在运行,你永远不会改变策略.OTOH处于系统运行期间的状态模式情况下,您可以根据需要随意更改状态.


Rav*_*abu 9

当您为特定任务使用多个算法时,将使用策略模式,并且客户端决定在运行时使用的实际实现.

来自wiki策略模式文章的UML图:

在此输入图像描述

主要特点:

  1. 这是一种行为模式.
  2. 它基于授权.
  3. 它通过修改方法行为来改变对象的内容.
  4. 它用于在算法族之间切换.
  5. 它在运行时更改对象的行为.

有关更多信息和实际示例,请参阅此帖子:

战略模式的现实世界范例

状态模式允许对象在其内部状态更改时更改其行为

来自wiki State模式文章的UML图 :

在此输入图像描述

如果我们必须根据其状态更改对象的行为,我们可以在Object中有一个状态变量,并使用if-else条件块根据状态执行不同的操作.状态模式用于提供通过上下文状态实现实现此目的的系统和丢失耦合方式.

有关更多详细信息,请参阅此journaldev文章.

sourcemakingjournaldev文章的主要区别:

  1. 国家战略之间的区别在于约束时间.该战略是一对一的模式,而国家更具活力.
  2. 国家战略之间的区别在于意图.使用Strategy,算法的选择相当稳定.使用State,"context"对象状态的改变使其从Strategy对象的"调色板"中进行选择.
  3. 上下文包含状态作为实例变量,并且可以有多个任务,其实现可以依赖于状态,策略模式策略作为参数传递给方法,上下文对象没有任何变量来存储它.


Rak*_* KR 5

策略和状态模式具有相同的结构。如果您查看两种模式的 UML 类图,它们看起来完全相同,但它们的意图完全不同。状态设计模式用于定义和管理对象的状态,而策略模式用于定义一组可互换的算法并让客户端选择其中一个。因此,策略模式是客户端驱动的模式,而对象可以自行管理状态。


pkg*_*ocz 5

用外行的语言,

在策略模式中,没有状态或所有状态都具有相同的状态.所有人都有不同的执行任务的方式,就像不同的医生以不同的方式对待同一患者的相同疾病.

在状态模式中,主观上存在状态,如患者的当前状态(例如高温或低温),基于该状态将决定下一个行动(药物处方).并且一个状态可以导致其他状态,因此存在状态陈述依赖性(技术上的组成).

如果我们在技术上试图理解它,基于两者的代码比较,我们可能会失去情境的主观性,因为两者看起来非常相似.