我正在阅读战略模式,并试图实施它,但我一直坚持决定战略实施,我觉得违反了开放封闭原则。
在策略模式中,我们编码接口并基于客户端交互,我们将传递策略实现。
现在,如果我们有一堆策略,那么我们需要决定使用哪种策略,客户选择像
这样的策略IStrategy str;
if(stragety1) {
str = new Strategy1()
} else if (stragety2) {
str = new Strategy2()
} and so on..
str.run()
现在按照开放式原则,上述内容对扩展名开放,但并未关闭修改
如果我将来需要添加其他策略(扩展名),我需要更改此代码。
有没有办法可以避免这种情况,或者我们需要如何实施战略模式?
答案 0 :(得分:2)
这确实不会因修改而关闭,但这是由于您初始化的方式。您正在使用值(枚举?)来确定应使用哪个策略子类。正如@bpjoshi指出他们的comment,这更像是一种工厂模式。
维基百科讨论战略模式如何support the Open/Closed Principle,而不是妨碍它
在该示例中,他们使用Car
类和Brake
策略。有些汽车用ABS制动,有些则没有。不同的Car
子类和实例可以给出不同的制动策略。
要关闭代码以进行修改,您需要以不同方式选择策略。您希望在定义新行为或子类的位置选择策略。您必须重构代码,以便在扩展代码时应用特定的策略子类。
答案 1 :(得分:2)
1)您必须将选择/创建 具体 策略与其用途分开。 I. e。使用函数selectStrategy
,将其作为(构造函数)参数传递等。
2)无法完全避免条件创建,但您可以隐藏它(例如,使用一些字典来映射state =>策略)和/或将其转移到应用程序的另一个级别。最后一种方法非常强大和灵活,但取决于任务。在某些情况下,您可以将选择/创建放在使用它的同一级别上。在其他情况下,您甚至可能最终将委托选择/创建到最高/最低级别。
2.1)您可以使用Registry
模式,并在添加新策略时避免修改“核心”对象。
答案 2 :(得分:0)
我认为,对于修改已关闭存在误解。
1988年,梅耶说:
当您的应用程序使用新功能进行扩展时,可能时,应该可以使用的软件。
和Rober C. Matrin说:
这个定义显然是过时的。 仔细考虑一下。如果系统中所有模块的行为都可以扩展而不进行修改,那么您可以向该系统 添加新功能,而无需修改任何旧代码 。这些功能仅通过编写新代码 来添加 。 https://8thlight.com/blog/uncle-bob/2014/05/12/TheOpenClosedPrinciple.html
在不修改旧代码的情况下添加一些新代码与Open-Closed Principle不冲突。
答案 3 :(得分:-1)
我认为你所指的决定应该是工厂阶级的责任。以下是一些示例代码:
public interface ISalary
{
decimal Calculate();
}
public class ManagerSalary : ISalary
{
public decimal Calculate()
{
return 0;
}
}
public class AdminSalary : ISalary
{
public decimal Calculate()
{
return 0;
}
}
public class Employee
{
private ISalary salary;
public Employee(ISalary salary)
{
this.salary = salary;
}
public string Name { get; set; }
public decimal CalculateSalary()
{
return this.salary.Calculate();
}
}
Employee类使用策略模式并遵循开放/封闭原则,即通过构造函数注入对新策略类型(ISalary实现)开放,但不接受修改。
缺少的部分是创建Employee对象的代码,如:
public enum EmployeeType
{
Manager,
Admin
}
public class EmployeeFactory
{
public Employee CreateEmployee(EmployeeType type)
{
if (type == EmployeeType.Manager)
return new Employee(new ManagerSalary());
else if (type == EmployeeType.Admin)
return new Employee(new AdminSalary());
etc
}
}
这是一个非常简单的工厂模式。有更好的方法可以做到这一点,但这是解释这个概念的最简单方法。