2

由于各种原因,我创建了自己的 Tree 实现,并提出了两个类,一个是“基”类,它是一个充满逻辑的通用树节点,另一个类扩展了更专业的类。

在我的基类中,某些方法涉及实例化新的树节点(例如添加子节点)。这些实例化在逻辑内部(例如在嵌套循环中),这使得逻辑难以与实例化分离。

因此,如果我不在特定类中覆盖这些实例,则会创建错误类型的节点。但是,我不想覆盖这些方法,因为它们还包含不应重复的共享逻辑!

问题可以归结为:

public class Foo {
    public String value() { return "foo"; }

    public Foo doStuff() {
        // Logic logic logic..
        return new Foo();
    }
}

class Bar extends Foo {
    public String value() { return "bar"; } 
}

new Bar().doStuff().value(); // returns 'foo', we want 'bar'

突然出现在我脑海中的第一件事是有一个扩展类可以覆盖的“创建钩子”:

public Foo createFooHook(/* required parameters */) {
  return new Foo();
}

现在。虽然这是一个很好的第一个想法,但从代码中散发出一股可怕的恶臭。有一些非常...的地方。

这就像光着身子做饭一样——感觉很危险,也没有必要

那么,你会如何处理这种情况呢?

4

3 回答 3

3

因此,在拿到我的设计模式副本并打开它之后,我确信这是我第一次发现我想要的东西。

它被称为工厂方法,它非常适合。它仍然有点难看,因为我的超类(Foo在上面的示例中)不是抽象的,这意味着子类不会被迫实现挂钩。

不过,这可以通过一些重构来解决,我最终会得到以下效果:

abstract class AbstractFoo {
    public String value() { return "Foo"; }

    public AbstractFoo doStuff() {
        // Logic logic logic
        return hook();
    }

    protected abstract AbstractFoo hook();
}

class Foo extends AbstractFoo {
    protected AbstractFoo hook() { return new Foo(); }
}

class Bar extends AbstractFoo {
    public String value() { return "Bar"; }

    protected AbstractFoo hook() { return new Bar(); }
}

new Bar().doStuff().value(); // Returns 'Bar'!
于 2008-09-29T09:44:04.387 回答
1

除了工厂模式之外,我还要看一下复合模式——它往往很适合在基于树的情况下使用工厂。

复合设计模式

于 2008-09-29T09:56:50.800 回答
0

我不认为有更好的方法。请注意不要从构造函数中调用这些钩子。

于 2008-09-29T09:22:06.623 回答