Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 战略模式还是无战略模式?_C#_Design Patterns_Strategy Pattern - Fatal编程技术网

C# 战略模式还是无战略模式?

C# 战略模式还是无战略模式?,c#,design-patterns,strategy-pattern,C#,Design Patterns,Strategy Pattern,在不涉及学术定义的情况下,假设当您有一个将执行操作的客户机代码上下文时使用策略模式,并且该操作可以通过不同的算法实现。例如: 使用哪种策略或算法取决于某些输入条件的许多情况。这就是为什么战略模式有时与工厂模式结合使用的原因。客户机将输入条件传递给工厂。然后,工厂知道必须制定哪些战略。然后,客户机执行所创建策略的操作 然而,我在一些场合遇到了一个在我看来恰恰相反的问题。要执行的操作总是相同的,但它将仅根据一系列输入条件执行。例如: public interface IStrategy {

在不涉及学术定义的情况下,假设当您有一个将执行操作的客户机代码上下文时使用策略模式,并且该操作可以通过不同的算法实现。例如:

使用哪种策略或算法取决于某些输入条件的许多情况。这就是为什么战略模式有时与工厂模式结合使用的原因。客户机将输入条件传递给工厂。然后,工厂知道必须制定哪些战略。然后,客户机执行所创建策略的操作

然而,我在一些场合遇到了一个在我看来恰恰相反的问题。要执行的操作总是相同的,但它将仅根据一系列输入条件执行。例如:

public interface IStrategy
{
    string FileType { get; }

    bool CanProcess(string text);
}

public class HomeStrategy : IStrategy
{
    public string FileType => ".txt";

    public bool CanProcess(string text)
    {
        return text.Contains("house") || text.Contains("flat");
    }
}

public class OfficeStrategy : IStrategy
{
    public string FileType => ".doc";

    public bool CanProcess(string text)
    {
        return text.Contains("office") || text.Contains("work") || text.Contains("metting"); 
    }
}

public class StragetyFactory
{
    private List<IStrategy> _strategies = new List<IStrategy>{ new HomeStrategy(), new OfficeStrategy() };

    public IStrategy CreateStrategy(string fileType)
    {
        return _strategies.Single(s => s.FileType == fileType);
    }
}
我是否错误地认为这是一种与战略模式不同的模式?尽管我在上面的代码中调用了Strategy,因为我在很多场合都是这样


如果这个问题与战略模式解决的问题不同,那么它是哪一种模式?

不是真正的战略模式,因为正如在

在计算机编程中,策略模式也称为 策略模式是一种行为软件设计模式,它支持 在运行时选择算法。而不是实施单一的 算法,代码接收运行时指令,以确定 要使用的一系列算法。[1]

您没有选择要在运行时执行的算法,只需检查条件以查看文件类型是否满足条件,然后执行算法

你认为这会改变吗?您是否需要它是可扩展的,以便将来如果需要根据文件类型执行不同的代码,您可以轻松地执行

如果这些问题的答案是肯定的,那么您可以保留策略并应用少量更改

首先定义定义要执行的代码的基本策略类

public abstract class StrategyBase
{
   public abstract bool CanProcess(string fileType);
   public virtual void Execute(File file)
   {
        _service.SaveInDatabase(file);
   }
}
你的策略会改变,从基础中衍生出来

public class HomeStrategy : StrategyBase
{
    public string FileType => ".txt";

    public override bool CanProcess(string text)
    {
        return text.Contains("house") || text.Contains("flat");
    }
}
//对其他战略实施同样的措施

正如评论中提到的,它不是一家真正的工厂,因为它不会在每次通话中都制定新的策略。它更像是一个提供基于文件类型执行的策略的提供者

public class StragetyProvider
{
    private List<StrategyBase> _strategies = new List<StrategyBase>{ new HomeStrategy(), new OfficeStrategy() };

    public StrategyBase GetStrategy(string fileType)
    {
        return _strategies.FirstOrDefault(s => s.CanProcess(fileType));
    }
}
注意,当您需要添加新条件时,只需实现一个从StrategyBase派生的新类,并将其添加到提供程序中的策略列表中,无需进行其他更改。若您需要为一些新的文件类型执行不同的逻辑,那个么您将创建新的策略并覆盖execute方法,仅此而已

如果这看起来真的像是一种过激行为,并且你不需要用新的行为来扩展这个解决方案&你唯一想要的就是能够添加新的条件,然后使用另一种方法

public interface ISatisfyFileType
{
    bool Satisfies(string fileType);
}

public class HomeCondition : ISatisfyFileType
{
    public string FileType => ".txt";

    public bool Satisfies(string text)
    {
        return text.Contains("house") || text.Contains("flat");
    }
}

// the rest of conditions
将所有条件合成一个

public class FileConditions
{
  private List<ISatisfyFileType> _conditions = new List<ISatisfyFileType>{ new HomeStrategy(), new OfficeStrategy() };

  public bool Satisfies(string fileType) =>
     _conditions.Any(condition => condition.Satisfies(fileType));

}

如果您需要一个新的条件而不涉及客户机代码,这还有实现一个新条件并将其添加到FileConditions类的好处。

这里的策略似乎不是真正可以互换的。文本文件策略不仅对docx文件效率低下,而且无法正常工作。这看起来应该是一个模板类,实例化的例子类似于C++中的STD::Cub。您的工厂刚刚返回基于文件扩展名选择的类的实例。它本质上与switch语句的作用相同。此外,如果在同一工厂中再次调用CreateStrategy,它将返回相同的对象。工厂的用户可能会从一个名为Create的方法中发现这一点,这可能会导致bug。谢谢你的回答@Michael。你说得很清楚,我对此表示怀疑是对的。我似乎多次将这种实施称为战略。也许这是因为它没有名字。最后,这是一个反复出现的问题:如何在不更改客户机代码的情况下向逻辑添加更多条件?。解决方案就是上面的实现。
public interface ISatisfyFileType
{
    bool Satisfies(string fileType);
}

public class HomeCondition : ISatisfyFileType
{
    public string FileType => ".txt";

    public bool Satisfies(string text)
    {
        return text.Contains("house") || text.Contains("flat");
    }
}

// the rest of conditions
public class FileConditions
{
  private List<ISatisfyFileType> _conditions = new List<ISatisfyFileType>{ new HomeStrategy(), new OfficeStrategy() };

  public bool Satisfies(string fileType) =>
     _conditions.Any(condition => condition.Satisfies(fileType));

}
public class Client
    {
        public void Execute()
        {
            var files = repository.GetFilesFromDisk();
            var fileTypeConditions = new FileConditions();

            foreach (var file in files)
            {
                if (fileTypeConditions.Satisfies(file.ContentText))
                {
                    service.SaveInDatabase(file);
                }
            }
        }
    }