0

Here is one design dilemma I have...

In my program, I have different kind of entries - numeric, textual, date, image, etc.

My first idea was to have model structured with inheritance like this:

Entry 
    -- NumericEntry (extends Entry)
    -- TextualEntry (extends Entry)
    -- DateEntry (extends Entry)
    -- ImageEntry (extends Entry)

Then I can have a list of Entry objects, and each object will know how to handle & expose its data through common members (i.e. showData(), makeSummary() etc.) If I want to add new Entry object, I will just add another class with that specific type.

But, java limitations, and also android orm libraries limitations makes this pretty complicated.

So, I have turned to composite pattern, but I am not sure if I am approaching it right.

So, now I have this (pseudocode):

 class Entry
    {
    Type type;
    (nullable)NumericEntry  numericEntry;
    (nullable)TextualEntry textualEntry;
    (nullable)DateEntry dateEntry;
    (nullable)ImageEntry imageEntry;

    public showData() 
    { 
        swicth (type) 
        {
          case numeric: ..
          case textual: ..
          case date: ..
          case image: ..
         }
    }
}

But this seems to me too wired, doesn't it? What would be right approach in the described scenario?

daneejela
  • 13,081
  • 7
  • 38
  • 50
  • 1
    The composition you've got there is not very nice indeed. What was the actual problems with inheriting from Entry? It seems like the obvious choice when looking at that switch statement. [Here's](http://stackoverflow.com/a/2399554/645270) some more info, notice the _is-a_ vs _has-a_. – keyser Jan 06 '17 at 12:37
  • I am using GreenDao (but I think it's similar for other orm's) for local storage. It has limited possibilities regarding inheritance, I can persist only subclass, and therefore queries return list of subclasses. But, now when I am rethinking it, it is not actually a problem, it actually make sense. Thanks for the comment! – daneejela Jan 06 '17 at 13:53
  • Using inheritance seems like a reasonable design option in this case. JDXA ORM for Android handles inheritance well. This blog gives some details about the inheritance support in JDXA (http://www.softwaretree.com/blog/2016/06/inheritance-support-in-jdxa-orm/). Disclaimer: I am the architect of JDXA ORM. – Damodar Periwal Jan 08 '17 at 22:23

2 Answers2

2

I think what you're trying to do is legit, but I think the composite pattern is a bit off here. The composite pattern is rather used for hierarchical structures, as far as I know (like directory structures).

Your model seems quite good, using an (abstract) base class, and let the other types extend from it, however I fail to understand why you want to have all the different types of entries in your base Entry class.

If I understand correctly what you want then this would be more logical.

Interface example:

public interface Entry{
    // Define all your methods as abstract and define them here
    void showData();
}

public class TextualEntry implements Entry{
     void showData(){
         // Your implementation for textual entries here
     }
}
// Repeat this for the other types of entries

You could also consider an abstract class implementation, which can define properties/fields used in all the extended classes. Moreover, you can implement methods in the abstract class which have the same implementation for all extended classes.

Abstract class example:

abstract class Entry{
    // Define your properties here that are used in all the other classes

    // Define all your methods as abstract and define them here
    public abstract void showData();
}

class TextualEntry extends Entry{
     // Define new properties here

     public override void showData(){
         // Your implementation for textual entries here
     }
}
// Repeat this for the other types of entries

On http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html they discuss a similar problem.

VinKel
  • 121
  • 7
  • Why not an interface? – keyser Jan 06 '17 at 12:36
  • 1
    An interface will work just as good for this basic case. However, abstract classes can have implementations of methods, and I can image that there will be some method on the Entry class of which the implementation is the same for all the inherited types. I'll add an example with an interface! – VinKel Jan 06 '17 at 12:47
1

If I understand your request correctly you can use Composite, but I did not get how you came to pseudo code.

Composite pattern compose objects into tree structures to represent part-whole hierarchies. Group of objects is to be treated in the same way as a single instance of an object.

Component interface defines common method/methods for leafs and composites.

Leaf implements Component interface, but catch is that you can have multiple leaf objects(numeric, text, ...).

Composite implements Component interface, but it is container for leaf objects as well.

So usage can be:

Component leaf1 = new Leaf(); //numeric entry
Component leaf2 = new Leaf(); // text entry

Composite composite = new Composite();
composite.add(leaf1);
composite.add(leaf2);

composite.operation(); // showData()
dstar55
  • 938
  • 6
  • 11