在使用设计模式时,您可以在多大程度上防止修改现有代码?

Posted

技术标签:

【中文标题】在使用设计模式时,您可以在多大程度上防止修改现有代码?【英文标题】:Up to what extent can you prevent modifying existing code when using design patterns? 【发布时间】:2015-07-04 16:22:49 【问题描述】:

我正在学校学习设计模式课程,并且已经阅读了 Head First Design Patterns 的一些章节。我想知道的是设计模式在多大程度上可以防止重写现有代码。

让我们以Duck 类和FlyBehavior 类为例。我在public static void main(String[] args) 中有以下代码:

Duck mallard = new MallardDuck(new FlyWithWings());

我是否正确地说,当您想添加新策略时,您将不得不修改您的 main() 方法?这样,您正在修改现有代码,对吗?我特指提到具体策略类的部分:new FlyWithWings().

如果您在代码中实现了工厂方法模式,则可以完全避免提及具体类 (FlyWithWings):

public FlyBehavior returnBehavior(FlyBehaviorFactory factory, String behaviorType) 
    return factory.getFlyBehavior(behaviorType);

因此,有以下代码行:

Duck mallard = new MallardDuck(returnBehavior(flyFactory, "wings"));

这样,您程序的某个部分不必知道要使用什么 FlyBehaviorFactory。然而,您的main() 方法仍然必须在 returnBehavior 方法中指定某些参数,以便知道哪个工厂将创建什么策略。因此,如果我添加了一个新的 FlyBehavior 类并希望将其作为参数添加到 returnBehavior(),我是否还需要修改 main()

可以进一步改善这种情况吗?

【问题讨论】:

你应该看看dependency injection 和它的各种框架。 @Synchro 请阅读:What should I do when someone answers my question 【参考方案1】:

你在这里做的是依赖注入,你将 FlyBehaviour 注入到 Duck 中。有时当使用像这样的依赖注入时,你可以有一个注入链。例如,如果您希望将速度策略注入到 FlyBehaviour 中,您可能会有类似的内容。

Duck mallard = new MallardDuck(new FlyWithWings(new FastSpeed()));

如果 main 和任何其他使用 Duck 的类必须了解所有这些类并且每次都必须更改这些类,那就不好了。更好的解决方案是使用一个依赖注入容器,它负责创建这些类中的每一个。然后在main中你可以调用这样的东西

Duck mallard = (Duck) Container.get('Duck');

容器负责创建注入所需的所有实例。因此,要回答您的问题,您需要在需要新策略时更改代码,但至少这样它只在一个地方,而不是在整个代码中,可能有很多文件。

【讨论】:

【参考方案2】:

在当前示例中,您对传递给工厂的参数进行硬编码,从而决定compile time 处的行为。

Duck mallard = new MallardDuck(returnBehavior(flyFactory, "wings"));

这可以更改为在 runtime 而不是 compile time 插入特定行为:

Duck mallard = new MallardDuck(returnBehavior(flyFactory, args[0]));

通过上述更改,您将永远不必更改您的main 方法。当运行时收到的行为不可用时,您的工厂可以以 throwsexception 的方式编写:

if(behaviorType.equals("wings") 
   //...create FlyWithWings
 else
  //throw an appropriate exception indicating that the behavior does not exist

话虽如此,如果引入新行为,更改代码是不可避免的。虽然,此更改将在一个地方,并且在您的应用程序中尽可能地落后,即您的factory,这首先是factory 的全部意义。此外,当您创建新的FlyBehavior 时,您是通过从现有类扩展来实现的。这与open-closed principle 内联

【讨论】:

以上是关于在使用设计模式时,您可以在多大程度上防止修改现有代码?的主要内容,如果未能解决你的问题,请参考以下文章

给出 SIGTERM 后,在多大程度上可以依赖写入磁盘?

ImageMagick 在将 PSD 文件转换为 GIF、PNG、JPG 文件时可以在多大程度上保留剪切路径?

Selenium WebDriver:我可以在多大程度上依赖 JavaScript?

PostgreSQL 在多大程度上支持并行 DDL?

损失函数

.神经网络的学习—损失函数