战略设计模式和国家设计模式之间的区别是什么?我在网上浏览了不少文章,但看不出明显的区别。

有人能用外行的语言解释一下吗?


当前回答

考虑一个处理客户呼叫的IVR(交互式语音应答)系统。你可能想要编程它来处理客户:

工作日 假期

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

节假日:IVR简单地回复说“只能在工作日上午9点到下午5点之间接听电话”。 工作日:它通过将客户连接到客户服务主管来响应。


这个连接客户和支持高管的过程本身可以使用一个策略模式来实现,其中高管是根据以下任何一个来挑选的:

轮循 最近最少使用 其他基于优先级的算法

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

其他回答

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

状态存储对包含它们的上下文对象的引用。战略则不然。 状态可以替换自己(IE:将上下文对象的状态更改为其他状态),而策略则不能。 策略作为参数传递给上下文对象,而状态由上下文对象本身创建。 策略只处理一个特定的任务,而状态为上下文对象所做的所有(或几乎所有)事情提供底层实现。

一个“经典”的实现将匹配列表中的每个道具的状态或策略,但你也会遇到混合了两者的情况。具体是国家层面的还是战略层面的,最终是一个主观问题。

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

在我看来,主要的区别在于他们的意图。从技术上讲,国家和战略模式看起来非常相似。 主要区别在于:

State模式在需要时更改上下文的状态,并且状态可以多次更改。context改变它的状态或者状态可以设置另一个状态 战略模式决定战略,战略很少会改变,而环境不会改变战略。

策略模式。

我们抽象出一些合理的策略:

public interface ISound
{
    void Make();
}   
    

及其具体策略:

public class DogSoundStrategy : ISound
{
    public void Make()
    {
        Console.WriteLine("Bar");
    }
}

public class CatSoundStrategy : ISound
{
    public void Make()
    {
        Console.WriteLine("Meow");
    }
}

这是对能发声的Animal的抽象描述:

public abstract class Animal
{
    public void MakeSound(ISound sound)
    {
        sound.Make();
    }
}

具体的动物是这样的:

public class Dog : Animal
{
}

public class Cat : Animal
{   
}

然后我们可以像这样调用上面的代码:

Dog dog = new Dog();
dog.MakeSound(new DogSoundStrategy()); // there is a small chance 
    // that you want to change your strategy

Cat cat = new Cat();
cat.MakeSound(new CatSoundStrategy()); // there is a small chance 
    // that you want to change your strategy

有一个小的机会,你想要改变你的策略。

状态模式

想象一下,你有一个电脑游戏,英雄可以是世界上任何一个超级人物。让我们称他为英雄。他能跑、能游、能飞,还能变成钢铁侠或蜘蛛侠。你有一个按钮,你可以改变它的形状或状态为钢铁侠或蜘蛛侠。

英雄的代码是这样的:

public class Hero
{
    IState _state;

    public Hero()
    {
        _state = new SpiderManState();
    }

    public void Run()
    {
        _state.Run();
    }

    public void Swim()
    {
        _state.Swim();
    }

    public void Fly()
    {
        _state.Fly();
    }

    public void ChangeShape()
    {
        _state = _state.SetShape();
    }
}

IState的接口看起来像这样:

public interface IState
{
    void Run();

    void Swim();

    void Fly();

    IState SetShape();
}

具体的状态是这样的:

public class SpiderManState : IState
{
    public void Fly()
    {
        Console.WriteLine("Spiderman is flying");
    }

    public void Run()
    {
        Console.WriteLine("Spiderman is running");
    }

    public void Swim()
    {
        Console.WriteLine("Spiderman is swimming");
    }

    public IState SetShape()
    {
        return new IronManState();
    }
}

IronManState会是这样的:

public class IronManState : IState
{
    public void Fly()
    {
        Console.WriteLine("IronMan is flying");
    }

    public void Run()
    {
        Console.WriteLine("IronMan is running");
    }

    public void Swim()
    {
        Console.WriteLine("IronMan is swimming");
    }

    public IState SetShape()
    {
        return new SpiderManState();
    }
}

现在通过点击英雄类的ChangeShape()按钮,你将能够改变英雄的状态, 例:从蜘蛛侠到钢铁侠。

因此,上下文状态(英雄)取决于并可以通过其按钮ChangeShape进行更改。这种情况会发生很多次。

您很有可能希望更改上下文的状态。

状态模式也可以被认为是替代类中许多if - else语句的一种选择。

这是一个相当老的问题,但我也在寻找同样的答案,这就是我所发现的。

对于状态模式,让我们考虑一个中间播放器播放按钮的例子。当我们开始播放时,它开始播放,并让上下文意识到它正在播放。每次客户端想要执行播放操作时,他都会检查播放器的当前状态。现在客户端知道对象的状态是通过上下文对象播放的,所以他调用暂停状态对象的动作方法。客户端实现状态的部分以及它需要在什么状态上执行操作的部分可以被自动化。

https://www.youtube.com/watch?v=e45RMc76884 https://www.tutorialspoint.com/design_pattern/state_pattern.htm

在策略模式的情况下,类图的安排与状态模式相同。客户来此安排做一些操作。也就是说,不同的算法取代了不同的状态,比如需要对模式进行不同的分析。在这里,客户端告诉上下文它想做什么,用什么算法(业务定义的自定义算法),然后执行。

https://www.tutorialspoint.com/design_pattern/strategy_pattern.htm

两者都实现了开闭原则,因此开发人员可以向状态模式和新算法中添加新的状态。

但不同之处在于它们使用的是基于对象状态执行不同逻辑的状态模式。在战略的案例中有不同的逻辑。

策略模式涉及到将算法的实现从宿主类移到单独的类中。这意味着宿主类不需要提供每个算法本身的实现,这很可能导致不干净的代码。

排序算法通常被用作一个例子,因为它们都做同样的事情(排序)。如果将每个不同的排序算法放入自己的类中,那么客户机可以轻松地选择使用哪种算法,并且模式提供了访问算法的简单方法。

状态模式涉及当对象的状态发生变化时改变对象的行为。这意味着宿主类不需要为它可能处于的所有不同状态提供行为的实现。宿主类通常封装提供给定状态下所需功能的类,并在状态改变时切换到不同的类。