3

我正在构建一个包含大量类的系统,所有这些类都共享通用功能,但也有少量由重叠的类子集共享的功能。实现这一点的最佳方法是什么?

我将以 SVG 为例(我正在为化学实现一个子集),尽管我在其他领域(例如化学)也有示例。这个问题和相关问题在 XML 模式中有明确的、不可变的设计规范。

有一个SVGElement具有许多通用功能的基类。所有其他类 ( SVGLine, SVGCircle...) 都直接派生自此。然后,它们具有规范中定义的其他功能(通过 XML 属性),例如:

 - x
 - width
 - fill
 - opacity

还有很多。请注意,设计是给定的——我们不能重新创建新的元素或属性。例如 SVG 既有circleand ellipse(经典问题),一个使用r(adius),另一个使用widthand height。在子类共享通用功能的地方,它们可以使用通用代码。

似乎有以下解决方案:

  • 在每个子类中实现每个函数。(容易出错且乏味)
  • 实现超类(SVGElement)中的所有功能并使派生方法无操作。(对于开发人员来说,臃肿、不可读和令人沮丧)
  • 创建接口 ( hasWidth) 并为每个 ( WidthImplementor) 创建一个委托子类。然后每个类都有一个接口列表(每个 SVG 属性最多可能有 20 个),并且可能有 100-200 个这样的实现者。
  • 从架构自动生成代码。我已经尝试过了,它运行起来很笨拙,但我没有一个漂亮的实现。它也不容易维护(注意大多数 XML-to-Java 系统不适合构建库系统,所以我必须自己做很多事情)

也许还有其他人。

我知道还有其他关于如何设计抽象的 SO 问题,但在这里基本上是固定的。我想要一个通用的解决方案,而不仅仅是一个 SVG 解决方案(用作一个可以理解的示例)。例如,化学标记语言 (CML) 也有 100-200 个子类和 100-200 个属性,分布在一个稀疏矩阵中。

4

1 回答 1

2

您可能需要考虑将“通用”功能实现为“装饰器”。然后,您可以在解析 SVG 元素时在运行时应用这些装饰器。

abstract class SVGElement {

    public void draw (void) {
        return;
    }

    public boolean hasWidth (void) {
        return false;
    }

    public boolean hasHeight (void) {
        return false;
    }

    // ..
}

// An abstract decorator
abstract class SVGElementDecorator extends SVGElement {

    protected SVGElement decoratedElement;

    public SVGElementDecorator (SVGElement decoratedElement) {
        this.decoratedElement = decoratedElement;
    }

    public void draw (void) {
        decoratedElement.draw ();
    }
}

// Decorator to add width functionality
class WidthDecorator extends SVGElementDecorator {

    private double width;

    public WidthAndHeightDecorator (SVGElement decoratedElement) {
        super(decoratedElement);
    }

    // override base class implementation
    public boolean hasWidth (void) {
        return true;
    }

    // implement a new method
    public double getWidth (void) {
        return width;
    }

    public void draw (void) {

        // do special stuff for width
        // ..

        // then draw the rest
        decoratedElement.draw ();
    }
}

然后,当你看到一个椭圆时:

SVGElement ellipse = new SVGElement();
ellipse = new WidthDecorator (ellipse);
ellipse = new HeightDecorator (ellipse);
于 2012-05-01T10:06:01.260 回答