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

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


当前回答

这两种模式都用于改变对象的行为,

按照设计,状态模式对象只有一个状态,对象的行为基于实现的单个状态(类)及其子类。

相反,策略没有单一的状态,对象的行为是由不同策略对象的实现决定的。

其他回答

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

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

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语句的一种选择。

用外行的话来说,

在策略模式中,没有状态或所有状态相同。 每个人都有不同的方法来完成一项任务,就像不同的医生用不同的方法来治疗同一种疾病,同一种状态的同一病人。

在state Pattern中,主观上存在状态,如患者当前的状态(如高温或低温),据此决定下一步的行动(药物处方)。一个状态可以导致另一个状态,因此存在状态之间的依赖关系(技术上来说是组合)。

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

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

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

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

这两种模式都委托给一个基类,这个基类有几个派生类,但是只有在State模式中,这些派生类才保留对上下文类的引用。

从另一个角度来看,战略模式是国家模式的简单版本;如果你愿意,也可以称之为子模式。这实际上取决于你是否希望派生状态保留对上下文的引用(即:你是否希望它们调用上下文上的方法)。

更多信息:Robert C Martin (& Micah Martin)在他们的书《c#中的敏捷原则、模式和实践》中回答了这个问题。(http://www.amazon.com/Agile-Principles-Patterns-Practices-C/dp/0131857258)