如何在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)?的主要内容,如果未能解决你的问题,请参考以下文章

SOLID原则(OOD&OOP)

如何在目标 c 中从 int 转换为字符串:示例代码

利用开闭原则 (SOLID)

“开-闭”原则 (Open-Closed principle, OCP)

在 C# 中从锯齿状数组转换为双指针

Facade模式是否违反SOLID原则?