首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >战略模式还是没有战略模式?

战略模式还是没有战略模式?
EN

Stack Overflow用户
提问于 2020-01-15 07:16:15
回答 1查看 1.1K关注 0票数 0

在不输入学术定义的情况下,假设在具有执行操作的客户端代码(上下文)时使用了策略模式,并且可以以不同的方式(算法)实现此操作。例如:https://www.dofactory.com/net/strategy-design-pattern

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

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

代码语言:javascript
复制
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);
    }
}

现在,客户端代码将从某个存储库获取文件,并将文件保存在数据库中。这就是操作,将文件存储在数据库中,这取决于文件的类型和每个文件的特定条件。

代码语言:javascript
复制
    public class Client
    {
        public void Execute()
        {
            var files = repository.GetFilesFromDisk();
            var factory = new StragetyFactory();

            foreach (var file in files)
            {
                var strategy = factory.CreateStrategy(file.Type);

                if (strategy.CanProcess(file.ContentText))
                {
                    service.SaveInDatabase(file);
                }
            }
        }
    }

我是否错误地认为这是一种与战略模式不同的模式?(尽管我在上面的代码中调用了策略,因为我在几次场合都是这样的)

如果这个问题与策略模式所解决的问题不同,那是哪种模式呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-01-15 08:48:27

并不是真正的战略模式,因为正如维基百科的策略模式中的定义所说:

在计算机编程中,策略模式(也称为策略模式)是一种行为软件设计模式,它允许在运行时中选择算法。代码不是直接实现单个算法,而是接收运行时指令,说明在一系列算法中使用哪种算法。

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

你认为这种情况会永远改变吗?您是否需要这是可扩展的,以便将来如果您需要根据文件类型执行不同的代码,您可以很容易地执行它。

如果对这些问题的回答是yes,那么您可以保留策略并应用很少的更改。

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

代码语言:javascript
复制
public abstract class StrategyBase
{
   public abstract bool CanProcess(string fileType);
   public virtual void Execute(File file)
   {
        _service.SaveInDatabase(file);
   }
}

你的策略改变为从基础开始。

代码语言:javascript
复制
public class HomeStrategy : StrategyBase
{
    public string FileType => ".txt";

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

//为其他战略实施同样的战略.

正如在评论中提到的,它并不是一个真正的工厂,因为它没有为每一个呼叫创建一个新的策略。它更像是一个提供基于文件类型的执行策略的提供者。

代码语言:javascript
复制
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));
    }
}

因此,客户端代码变得简单得多:

代码语言:javascript
复制
public class Client
    {
        public void Execute()
        {
            var files = repository.GetFilesFromDisk();
            var provider = new StragetyProvider();

            foreach (var file in files)
            {
                var strategy = provider.GetStrategy(file.Type);
                strategy?.Execute(file);
            }
        }
    }

注意,当您需要添加新条件时,只需实现一个从StrategyBase派生的新类,并将其添加到提供程序中的策略列表中,而不需要进行其他更改。如果您需要为某些新的文件类型执行不同的逻辑,您将创建新的策略和override执行方法,仅此而已。

如果这看起来确实有点过火,并且您不需要用新的行为来扩展这个解决方案&您唯一想要的就是能够添加新的条件,那么可以使用另一种方法。

代码语言:javascript
复制
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

把所有的条件组合成一个

代码语言:javascript
复制
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));

}

客户:

代码语言:javascript
复制
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);
                }
            }
        }
    }

这还可以实现一个新条件,并在不接触客户端代码的情况下将其添加到FileConditions类中。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59746652

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档