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

5.8k Views Asked by At

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?

1

There are 1 best solutions below

2
Anders Johansen On BEST ANSWER

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.