如何在SOLID中从条件语句转换为OCP(Open Closed Principle)?
Posted
技术标签:
【中文标题】如何在SOLID中从条件语句转换为OCP(Open Closed Principle)?【英文标题】:How to convert from conditional statements to OCP (Open Closed Principle) in SOLID? 【发布时间】:2019-10-10 12:54:05 【问题描述】:我有一个基于传递的字符串值执行各种数据库检查的代码。我可以用多个条件语句(if 和 else)来解决它,我绝对知道它打破了 Solid 原则中的 OCP,因为它可以修改。我已经想到了解决这个问题的方法,但这只会使代码库复杂化。 (简单是关键)
最好的方法是什么?
目前,我已尝试创建一个由类实现的接口,但我无法根据传递的值进行评估,因为它执行所有实现该接口的类
示例 如果有传递的字符串,例如“cook”、“bake”、“sleep”和“fight”。 我不想写: if(action == 'cook') 然后执行此操作 或者 if(action == 'bake') 然后执行此操作 或者 if(action == 'sleep') 然后执行此操作 或者 if(action == 'fight') 然后这样做
我所做的是创建一个界面
public interface Iaction
public bool Act();
//then create various classes that implemented the interface
public class Sleep: Iaction
public bool Act()
.....
public class Cook: Iaction
public bool Act()
.....
public class Bake: Iaction
public bool Act()
.....
public class Fight: Iaction
public bool Act()
.....
如果传递的动作是厨师,就会出现主要问题。我只想执行厨师方法。 Iaction.Act();执行所有实现该接口的类。
public IHttpActionResult ThingToDo(string action)
if(string.IsnullOrEmpty(action) == false)
bool response = Iaction.Act();
....
....
...
有没有办法在 Solid Principle 中使用 OCP 实现这一目标?
【问题讨论】:
请分享代码,你尝试执行的地方Iaction.Act()
。
你必须通过依赖注入将期望的行为(cook, bake...)注入到类中。
@Fildor 我已经编辑了问题
这没有意义。 Act
不是静态方法,是吗?应该有类似Iaction localAction = .... ; localAction.Act();
@Fildor,你是对的......然后我可以根据传递的操作值进行实例化。猜猜,我忽略了这一点。我可以创建一个工厂方法来处理它。谢谢
【参考方案1】:
我建议你用策略模式替换条件逻辑来解决这种情况。
搜索“用策略替换条件逻辑” Martin Fowler 的书并阅读 Joshua Kerievsky 的 "Refactoring to Patterns: Simplification"
OCP 由您添加策略而不更改代码(最多更改确定要应用的策略的工厂)这一事实来保证
uml:
【讨论】:
【参考方案2】:为自己创建一个工厂方法,该方法根据您的参数返回接口的具体类。即类似:
public static IAction ResolveAction(string actionName)
///logic here
那么您的实现代码将如下所示:
IAction actionToExecute = ActionFactory.ResolveAction(actionName);
actionToExecute.Act();
为避免在该函数中使用 switch 或 if 语句,可以:
使用反射按需加载实现 IAction 的适当类。您需要通过约定适当地命名类以执行此操作..即“cook”映射到 CookAction 等。
使用支持命名实例的依赖注入容器,并在您的工厂方法中,通过名称从容器中解析类实例,其中实例名称映射到参数值。
【讨论】:
【参考方案3】:目标:
-
Act() 基于 string:action.
在不违反 OCP 的情况下执行 #1。
public interface Iaction
public bool Act(string action);
//then create various classes that implemented the interface
public class Sleep: Iaction
public bool Act(string action)
if(action == 'zzz')
//do something
else
//do nothing
...
如果不能改变Act()方法,可以创建setAction(string action)方法,将string:action保留在继承类中,Act()基于字符串。
客户端应该如下所示。
var listIaction = new ArrayList<Iaction>();
public IHttpActionResult ThingToDo(string action)
foreach(Iaction obj in listIaction)
bool response = obj.Act(action);
...
public IHttpActionResult ThingToDo2(string action)
foreach(Iaction obj in listIaction)
obj.setAction(action);
bool response = obj.Act();
...
【讨论】:
以上是关于如何在SOLID中从条件语句转换为OCP(Open Closed Principle)?的主要内容,如果未能解决你的问题,请参考以下文章