策略模式电影条件从主要 class 到客户端代码,那有什么意义呢?

Strategy pattern movies conditionals from inside the main class to the client code, so what's the point?

我正在尝试理解策略模式,这里有一个例子,我们有一个Customer有一个方法GetDiscount,这个方法写成如下

GetDiscount
    If (Condition1)
        Return 10%
    else (Condition2)
        Return 20%

现在我已经使用策略模式重构了代码,所以它变成了

GetDiscount
     Invoke the attached strategy

并且我们创建了两个策略class10%Strategy20%Strategy来封装折扣的行为

而对于使用客户 class 的客户端代码,它变为

c = new Customer

if(condition1)
c.attach(10%Strategy)
else (condition2)
c.attach(20%Strategy)

c.GetDiscount

正如您所看到的,我们已经将 Customer class 内部的条件转移到客户端代码中,不仅如此,而且这个条件分支本身被认为是一种业务逻辑,我们让它泄漏到可能是演示控制器的客户端代码中。

我是不是漏掉了什么?

在使用面向对象技术开发的大型软件系统中,您有组装对象的代码和使用组装对象的代码。在您的情况下,调用 attach 的代码正在组装 Customer 对象供以后使用,调用 GetDiscount 的代码是使用该对象的代码。

策略模式实现的目标是将 Customer 获得哪个折扣的决策从对象的使用点转移到对象的组装点。该条件保留在您的代码中,但现在仅限于您创建 Customer 对象的地方。

组装完成后,Customer 对象就可以自给自足了。不再需要用于计算 10% 或 20% 折扣条件的数据,因为它嵌入在折扣类型中。计算折扣的逻辑遵循代码中不同位置的 Customer。您可以使用折扣计算而无需在多个地方重复逻辑 - 例如,计算销售总价、预览单个商品的价格、处理 return,等等。当多次需要计算时,这也可以避免重复相同的逻辑。

核心点:

c = new Customer
if(condition1)
  c.attach(10%Strategy)
else (condition2)
  c.attach(20%Strategy)
c.GetDiscount

可能是您不会手动编写的代码。换句话说:在较大的 "real world" 应用程序中,您 避免 为 "real business" 对象调用 new。相反,您依赖于为您执行 依赖注入 的框架。

换句话说:您部署的应用程序具有特定的配置。然后 framework 代码决定创建什么样的对象;以及如何配置它们。

从这个意义上说,替代实施可以变成:

if(condition1)
  c = new Customer10%
else (condition2)
  c = new Customer20%
c.GetDiscount

意思:你转向多态;并让您的 DI 框架根据 "configuration knowledge".

创建所需的特定客户 class

有趣的是,关于这些概念的一些 "further food for thought" 可以在第 1 号视频中找到。 2 来自 videos 关于编写可测试代码的内容。