Implementing subclasses with sparse common functionality

I am creating a system with a large number of classes, all of which have common functionality, but also have less functionality, shared by overlapping subsets of classes. What are the best ways to implement this?

I'll take SVG as an example (I implement a subset for chemistry), although I have examples in other areas, such as chemistry. These and related issues have clear, unchanging, constructive specifications in XML schemas.

There is a base class SVGElementthat has a lot in common. All other classes ( SVGLine, SVGCircle...) directly follow from this. Then they have other functionality defined in the specification (via XMLattributes), for example:

 - x
 - width
 - fill
 - opacity

and much more. Please note that design is given - we cannot recreate new elements or attributes. For example, SVG has both circle, and ellipse(classic problem), and one uses r(adius), others widthand height. If subclasses have common functionality, they can use common code.

It seems that the following solutions exist:

  • implement every function in every subclass. (Vulnerability to errors and tedious)
  • implement all functions in a superclass (SVGElement) and make no-ops derived methods. (Bloated and unreadable and frustrating for developers).
  • create interfaces ( hasWidth) and subclass a delegate for each ( WidthImplementor). Each class then has a list of interfaces (possibly up to 20 for each SVG attribute), and possibly 100-200 such developers.
  • . , , . ( , XML-Java , )

, , .

, , , . , SVG ( ). , (CML) 100-200 100-200 , .

+3
1

, , "" " 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);
+2

All Articles