3

私は、すべてが共通の機能を共有するが、クラスのサブセットをオーバーラップすることによって共有される機能の量が少ない多数のクラスでシステムを構築しています。これを実装する最良の方法は何ですか?

例として、SVG(化学のサブセットを実装しています)を取り上げますが、化学などの他の分野の例もあります。これと関連する問題には、XMLスキーマの明確で不変の設計仕様があります。

SVGElement多くの共通機能を持つ基本クラスがあります。他のすべてのクラス(SVGLineSVGCircle...)は、これから直接派生します。次に、次のような他の機能が(XML属性を介して)仕様で定義されます。

 - x
 - width
 - fill
 - opacity

などなど。デザインが指定されていることに注意してください。新しい要素や属性を再作成することはできません。たとえば、SVGにはcircleellipse(古典的な問題)の両方があり、一方は、、r(adius)もう一方はとを使用widthheightます。サブクラスが共通の機能を共有する場合、それらは共通のコードを使用できます。

次の解決策があるようです:

  • 各サブクラスに各関数を実装します。(エラーが発生しやすく、面倒です)
  • すべての関数をスーパークラス(SVGElement)に実装し、派生メソッドを操作なしにします。(膨満感があり、読みにくく、開発者にとって苛立たしい)
  • インターフェイス(hasWidth)を作成し、各()のデリゲートサブクラスを作成しますWidthImplementor。各クラスには、インターフェイスのリスト(SVG属性ごとに最大20個)があり、そのような実装者は100〜200個ある可能性があります。
  • スキーマからコードを自動生成します。私はこれを試しました、そしてそれは不格好に働きます、しかし私はきれいな実装を持っていません。また、簡単に保守することもできません(ほとんどのXMLからJavaへのシステムはライブラリシステムの構築には適していないため、これの多くを自分で行う必要があります)

そして多分他の人。

抽象化を設計する方法について他にもSOの質問があることは承知していますが、ここではほとんど修正されています。SVGソリューション(理解しやすい例として使用されています)だけでなく、一般的なソリューションが必要です。たとえば、Chemical Markup Language(CML)にも100〜200のサブクラスと100〜200の属性があり、スパース行列に分散しています。

4

1 に答える 1

2

'common'機能を' Decorators 'として実装することを検討することをお勧めします。その後、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 に答える