views:

129

answers:

4

I use the decorator pattern to describe Actions, and I would like to use those Actions in RPC calls

public abstract class Action implement Serializable
{
  boolean       isDecorated = false;
  public Action() {} // default constructor for Serialization
}

public abstract class ActionDecorator extends Action
{
  private   Action  _decoratedAction;

  public ActionDecorator()  // default constructor for Serialization
  {}

  public ActionDecorator(Action action)
  {
    _decoratedAction = action;
    _decoratedAction.isDecorated = true;
  }
}

After the transaction, I do receive a DecoratorAction wich contains an Action, but the isDecorated member of _decoratedAction is set to false.

Since the default (zero-arg) constructor is called to re-construct my object, both my decorator AND my decorated actions get the default value of isDecorated (false).

I can't copy the "_decoratedAction.isDecorated = true;" in the zero-arg constructor of ActionDecorator, because _decoratedAction is not initialized (null) at that time.

Sure I could manually set the boolean after each transaction, but it would be better to avoid extra object initialization (wich can be forgot) each time my co-workers want to use the Action object...

A: 

Maybe you could turn isDecorated into a method and have it always return false in Action, and override it in ActionDecorator to always return true. What is the purpose of isDecorated? Why does Action or its users need to know if Action is decorated or not?

Stevo Slavic
Overriding a method in ActionDecorator won't work: a decorator can be decorated.The need of isDecorated is very specific to my implementation and is not really the problem here: if a constructor of A takes an Object B that i want to initialize/modify, i can't figure how to send A across the the network without loosing de modifications i made to B
Garagos
A: 

What happens to the Action objects in the RPC call exactly? Are they persisted somewhere? If so your persistence definitions may not be correct.

Jes
+1  A: 

I've tried your code and it works just as expected.

I used Action and ActionDecorator as posted by you, but I made _decoratedAction public so I could check its value.

I then subclassed both classes:

class MyAction extends Action {
    public MyAction() {}
}

class MyActionDecorator extends ActionDecorator {
    public MyActionDecorator() {}
    public MyActionDecorator(Action a) {
        super(a);
    }
}

and declared a service method that would return an Action. This is its implementation:

public Action getAction() {
    return new MyActionDecorator(new MyAction());
}

After calling the service from the client, I print the action's state:

System.out.println(action.isDecorated); // false
System.out.println(((ActionDecorator) action)._decoratedAction.isDecorated); // true

Everything is as expected: isDecorated of the ActionDecorator is false and isDecorated of the Action decorated by it is true. Hope this helps in identifying your problem. If not, please provide more details.

fhd
A: 

It is just a improperly written decorator pattern. The Decorator should delegate all unimplemented methods to the object being decorated. So in your case you should have appropriate accessor (getter/setter) method for isDecorated in both Action and ActionDecorator. The accessor methods in ActionDecorator should delegate the request to _decoratedAction object.

Prem