oopdesign-patternsdecoratorfactory-patterndataabstract

Use decorator and factory together to add properties or specialize an object


I'm new to OOP and design pattern.

I've a simple app that handles the generation of Tables, Columns (that belong to Table), Rows (that belong to Column) and Values (that belong to Rows). Each of these object can be a collection of Property, which is in turn defined as an enum.

They are all interfaces: I used factories to get concrete instances of these products.

Now I'm facing the problem of extending these classes. Let's say I need another product called "SpecialTable" which in turn has some special properties or new methods like 'getSomethingSpecial' or an extended set of Property. The only way is to extend/specialize all my elements (ie. build a SpecialTableFactory, a SpecialTable interface and a SpecialTableImpl concrete)? Let's say I would still like to use standard methods like addRow(column, name) that has no need to be inherited...

I don't like the idea to inherit factories and interface, but since SpecialTable has more method I guess it cannot share the same factory. Am I wrong?

Another question: if I need to define product properties at run time (a Table that is upgraded to SpecialTable), I guess I should use a decorator. Is it possible (and how) to combine both factory and decorator design?


Solution

  • SpecialTable needs its own creation mechanism, so yes, it will need its own factory method (or factory class, if you are creating a group of items that must be related).

    Alternatively: You could use Design pattern Strategy for your factory. In that case you would configure the factory with the desired creation mechanism at runtime.

    As for the remaining question:

    The three most common ways to add functionality to a class are:

    1. Subclassing
    2. Design pattern Adaptor/Proxy, possibly combined with introspection. Categories are really a special case of this approach.
    3. Design pattern Visitor

    You have already considered subclassing.

    Design pattern Adaptor/Proxy is basically this: Create a new class that has the desired interface, and implements some (or all) of its methods by calling an instance of your existing class.

    For Design pattern Visitor you in a sense combine Proxy with "Double Dispatch". Your added functions reside in an object that can call an instance of your existing class. See Visitor pattern - adding new ConcreteElement classes is hard? for an example.

    Strategy:

    It works like this:

    public interface MyStrategyInterface {
      public void doWork();
    }
    
    public class MyStrategyAccessPoint implements MyStrategyInterface {
    
      private MyStrategyInterface current;
    
      public MyStrategyAccessPoint(final MyStrategyInterface initial) {
        current = initial;
      }
    
      public void doWork() {
        current.doWork();
      }
    
      public void setStrategy(final MyStrategyInterface newCurrent) {
        current = newCurrent;
      }
    }
    

    As you can see, you can now change which actual implementation of MyStrategyInterface is used at runtime. This pattern is often combined with Singleton, making MyStrategyAccessPoint and its doWork method static.