1

I have following problem: I am creating an aplication for creating UML diagrams. Right now just to simplify everything I assume only couple of available diagram elements:

  1. class
  2. interface
  3. generalization
  4. interface implementation
  5. association
  6. aggregation

I decided to create one common abstract class for all of that elements:

abstract DiagramElement which has 2 subclasses also abstract:

  1. DiagramRelation
  2. DiagramObject

Nextly DiagramRelation has 4 subclasses:

  1. Generalization
  2. InterfaceImplementation
  3. Assosication
  4. Aggregation

And DiagramObject has 2 subclasses:

  1. Interface
  2. Class

I really wanted to post a picture so it would be all much more simplier but I don't have enough reputation points so sorry.

I came across following problem: each of this element have a different visual representation, ie: interface has only methods etc so each of this element will need to be show differently - I don't want to use multiple "if" instructions for it.

I use WPF and I decided that every control will place it's contest into StackPanel which will be placed inside MyContextControl (inherits after ContextControl and add interface atribute):

public interface IDiagramElementDraw
{
    public StackPanel Draw();
}

public MyContextControl : ContextControl
{
    private IDiagramElementDraw _drawingInterface;
    private StackPanel context;
    public DrawControl()
    {
        context = _drawingInterface.Draw();
    }
} 

But I don't know which class should implement IDiagramElementDraw interface - I don't want to implement it at the level of Interface, Class, Generalization etc classes because I want them to only represent logical information about each element.

I would appreciate any help, feel free to post complete different solution - this one may be completely wrong, this was just my idea.

  • First: Any abstraction is characterized for the responsibility it has. What is the responsability of DiagramElement? Second: If you have subclassed it twice (DiagramAggregation and DiagramObject) it's because you plan that each one of them shall do the same responsability in its own manner. Which differences are expected between the beheviour of DiagramAggregation and DiagramObject? – Little Santi Jun 27 '15 at 15:25
  • @Little Sani Responsibility of DiagramElement is to represent all of the available elements (I wanted to create a list of DiagramElements to keep all created objects in one place, also all of the subclassed objects have common properties as: comment, name, type of access) I think You meant DiagramRelation not DiagramAggregation. DiagramRelation was suppose to be keep all of the relations betweens DiagramObjects in one place. DiagramObject is suppose to represent all of the actual objects like Class, Interface. Are You saing that I should completely seperate DiagramRelations? – JustARegularGuy Jun 27 '15 at 15:54
  • No, I dind't suggest anything concrete. I'm just saying that every abstraction has a proper responsibility (that is clear), and that every subclass decides *on its own* how to achieve it. So: A responsability is usually represented by *one method*, and a design decission is represented by *one overwritting method*. So I suggest you declare in DiagramElement one abstract method with all the necessary parameters to let the subclases decide how to implement it. In that way, there should be no need of IFs. – Little Santi Jun 27 '15 at 16:05
  • possible duplicate of [Interface vs Abstract Class (general OO)](http://stackoverflow.com/questions/761194/interface-vs-abstract-class-general-oo) – T.S. Jun 28 '15 at 04:10

3 Answers3

0

From my answer to another question:

Distinction between using an interface or an abstract class as a basis: An abstract class ia a shared implementation; an interface is a shared contract. They share some commonality, but meet different requirements. For instance, you might want to share requirements (a common interface IProjectile) between small arms and heavier weapons, or between lethal and non-lethal weapons, while implementing the three categories on three distinct abstract classes (LethalSmallArms, NonLethalSmallArms, and Howitzers) that all implement the common interface IProjectile.

From another answer of mine

An abstract class can, with care, be extended in a non-breaking manner; all changes to an interface are breaking changes.

Update: In contrast, an interface can be an in or out type-parameter and an abstract class cannot. Sometimes one or the other is more appropriate for a given design, and sometimes it is a toss-up.

Community
  • 1
  • 1
Pieter Geerkens
  • 11,775
  • 2
  • 32
  • 52
  • Hi @Peter Geerkens, so in a similarity to Your example I should stay with given hierarchy and implement my drawing interface on top of lowest classes in given hierarchy which are: Class, Interface, Generalization, InterfaceImplementation, Assosication and Aggreagation? I didn't want to do this because I wanted to seperate element's logical part fom part that decide how it should be drawn. – JustARegularGuy Jun 27 '15 at 16:19
  • @JustARegularGuy: Stop thinking of *interfaces* as types of *classes*; they aren't. Classes are implementations, virtual, abstract or concrete, and interfaces are the contracts *being implemented*. To some extent, an interface is a requirement and the classes implementing it are solutions of that requirement meeting additional constraints. – Pieter Geerkens Jun 27 '15 at 16:28
0

Generally speaking, both interfaces and abstract classes are useful; it just depends on WHO:

  • Interfaces are more desirable for someone to USE your API, for they gurantee him with absolute freedom.
  • Abstract classes are more desirable for someone to EXTEND your API, for they ease the task of extending.

The more sensitive option is to combine both: Desing a hierarchy of public interfaces (for using), and provide also abstract classes with the members mostly common to any implementation (for extending), and if you want to let the client extend your API, make them public.

And, in the bottom of all the hierarchy, private implementation classes are expected.

Little Santi
  • 8,563
  • 2
  • 18
  • 46
0

Using polymorphism could be a good solution and will prevent "if" conditions. 1. You could have an IDrawable interface that will have a Draw method on it. This interface will be implemented by you abstract class. 2. Then you will have an ElementDrawing and its derived classes which will draw the different types (classes, interfaces,...). It could be a virtual property that will be instantiated in each DiagramElement differently according to the type.

    class abstract DiagramElement : IDrawable
    {
        public abstract void Draw();   
    }


    class ClassDiagramElement:DiagramElement 
    {
        public overrides void Draw()
        {
           ElementDrawing elementDrawing = new ClassDrawing();
           elementDrawing.DrawElement(); 
        }
    }

    class InterfaceDiagramElement:DiagramElement 
    {
        public overrides void Draw()
        {        
           ElementDrawing elementDrawing = new InterfaceDrawing();
           elementDrawing.DrawElement([maybe need some parameters]); 
        }
    }

ElementDrawing is a base class for all the derived classes that draw the different elements in your UML. It can be defined as virtual property as mentioned above.

ehh
  • 3,412
  • 7
  • 43
  • 91