Не совсем шаблон стратегии, потому что, как определено в шаблоне стратегии в Википедии, говорит:
В компьютерном программировании шаблон стратегии (также известный как шаблон политики) является поведенческим шаблоном разработки программного обеспечения , который позволяет выбрать алгоритм во время выполнения . Вместо непосредственной реализации одного алгоритма код получает инструкции во время выполнения, которые в семействе алгоритмов использовать. [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));
}
}
В результате код клиента стал намного проще:
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
, и добавляете его в список стратегий в поставщике, и никаких других изменений не требуется. Если вам потребуется выполнить другую логику c для некоторого нового типа файла, вы создадите новую стратегию и override
Выполните метод, и все.
Если это так действительно выглядело как излишнее, и вам больше не нужно расширять это решение новым поведением, и единственное, что вам нужно - это иметь возможность добавить новое условие, тогда go, с другим подходом.
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);
}
}
}
}
Это также дает преимущество в реализации нового условия и добавлении его в класс FileConditions
, если вам нужен новый состояние без прикосновения к коду клиента.