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

Up to what extent can you prevent modifying existing code when using design patterns?

提问人:Synchro 提问时间:4/26/2015 最后编辑:Dave SchweisguthSynchro 更新时间:7/14/2016 访问量:133

问:

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

让我们以类和类为例。我在以下代码中:DuckFlyBehaviorpublic 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。然而,你的方法仍然必须在 returnBehavior 方法中指定某些参数,以便知道哪个工厂将创建什么策略。因此,我说如果我添加了一个新的 FlyBehavior 类,并且想将其作为参数添加到 中,您仍然需要修改吗?main()main()returnBehavior()

能否进一步改善这种情况?

Java 设计 方法 策略模式

评论

0赞 Seelenvirtuose 4/26/2015
您应该了解依赖注入及其各种框架。

答:

0赞 Chetan Kinger 4/26/2015 #1

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

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

这可以更改为在以下位置插入特定行为,而不是:runtimecompile time

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

通过上述更改,您将永远不必更改您的方法。你的工厂可以这样写,当运行时收到的行为不可用时:mainthrowsexception

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

话虽如此,如果引入新行为,更改代码是不可避免的。虽然,这种变化将在一个地方进行,并且尽可能落后于您的应用程序,即您的应用程序首先是重点。此外,当您创建一个 ,您是通过从现有类扩展来实现的。这与factoryfactoryFlyBehavioropen-closed principle

0赞 user2802557 7/14/2016 #2

你在这里做的是依赖注入,你正在将 FlyBehaviour 注入到 Duck 中。有时,当使用这样的依赖注入时,您可以有一连串的注入。例如,如果您希望将速度策略注入 FlyBehaviour,您可能会有这样的东西。

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

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

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

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