Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to remove decorated object from Decorator Pattern in Java

I'm reading "Design Pattern for Dummies". I read and practiced Decorator Pattern. With Decorator Pattern, we can decorate an object with anything. Now, I want to remove decorated object before decorated.I have solved this problem by an ArrayList but I still feel it's not good. Can you tell me how to remove a decorated object? And what is a better way?

this is my way:

Computer.java

public class Computer {

    public Computer() {
    }

    public String description() {
        return "computer";
    }

}

ComponentDecorator.java

public abstract class ComponentDecorator extends Computer {
    @Override
    public abstract String description();
}

CD.java

public class CD extends ComponentDecorator {
    private Computer computer;

    public CD() {
    }

    public CD(Computer computer) {
        this.computer = computer;
    }

    @Override
    public String description() {
        return computer.description() + " and a CD";
    }

}

Disk.java

public class Disk extends ComponentDecorator {
    private Computer computer;

    public Disk() {
    }

    public Disk(Computer c) {
        computer = c;
    }

    @Override
    public String description() {
        return computer.description() + " and a disk";
    }

}

Monitor.java

public class Monitor extends ComponentDecorator {
    private Computer computer;

    public Monitor() {
    }

    public Monitor(Computer computer) {
        this.computer = computer;
    }

    @Override
    public String description() {
        return computer.description() + " and a monitor";
    }

}

Main.java

import java.util.ArrayList;
import java.util.Arrays;

public class Main {
    static ArrayList<ComponentDecorator> list = new ArrayList<>();

    public static void main(String[] args) {
        addComponent(new CD(), new Disk(), new Monitor());
        System.out.println(list.size());
        Computer penIII = getComputer();
        removeComponent(new Monitor());
        penIII = getComputer();
        System.out.println(penIII.description());
    }

    private static void addComponent(ComponentDecorator... comp) {
        list.addAll(Arrays.asList(comp));
    }

    private static void removeComponent(ComponentDecorator comp) {
        for(ComponentDecorator c : list) {
            if(c.getClass() == comp.getClass()) {
                list.remove(list.indexOf(c));
                break;
            }
        }
    }

    private static Computer getComputer() {
        Computer c = new Computer();
        Class e;
        for(ComponentDecorator d : list) {
            e = d.getClass();
            try {
                c = (Computer) e.getConstructor(new Class[]{Computer.class}).newInstance(c);
            } catch(Exception ex) {
                ex.printStackTrace();
            }
        }
        return c;
    }
}
like image 584
Do Manh Avatar asked Sep 02 '12 21:09

Do Manh


People also ask

What is the difference between the proxy and the Decorator pattern?

Although Proxy and Decorator patterns have similar structures, they differ in intention; while Proxy's prime purpose is to facilitate ease of use or controlled access, a Decorator attaches additional responsibilities. Both Proxy and Adapter patterns hold a reference to the original object.

Does Decorator use inheritance?

The Decorator pattern allows extending (decorating) the functionality of an object. It is an alternative to inheritance. Decorator provides new functionality in run-time to a specific instance, while inheritance adds functionality at compilation time and the change affects all instances of the new class.

How does the Decorator design pattern work?

Decorator patterns allow a user to add new functionality to an existing object without altering its structure. So, there is no change to the original class. The decorator design pattern is a structural pattern, which provides a wrapper to the existing class.

What is a Decorator object?

In object-oriented programming, the decorator pattern is a design pattern that allows behavior to be added to an individual object, dynamically, without affecting the behavior of other objects from the same class.


2 Answers

A nicer way would be adding the "removeDecorator" method to your ComponentDecorator class.

public abstract class ComponentDecorator {

private ComponentDecorator subject;

public ComponentDecorator(ComponentDecorator subject) {
  this.subject = subject;
}

@Override
public abstract String description();
}

public void removeDecorator(ComponentDecorator toRemove) {
  if (subject == null) {
    return;
  } else if (subject.equals(toRemove)) {
    subject = subject.getSubject();
  } else {
    subject.removeDecorator(toRemove);
  }
}

public ComponentDecorator getSubject() {
  return subject;
}


// Computer
public class Computer extends ComponentDecorator{

public Computer() {
  super(null);
}

public String description() {
  return "computer";
}

// CD
public class CD extends ComponentDecorator {

  public CD(ComponentDecorator computer) {
    super(computer);
  }

  @Override
  public String description() {
    return getSubject().description() + " and a CD";
  }
}

// main
public static void main(String[] args) {
    ComponentDecorator penIII = new Computer();
    penIII = new CD(penIII);
    penIII = new Monitor(penIII);
    System.out.println(penIII.description());
}

}

If you don't have the reference of the decorator to remove, you can create another method that the a Class instead.

You'll need to the decorated object as "ComponentDecorator" instead of "Computer" however. I suggest to make the Computer class extends ComponentDecorator instead of the other way around.

like image 157
nwang0 Avatar answered Oct 13 '22 03:10

nwang0


I suspect I'm misunderstanding your question, but to get the decorated (inner) object out of the decorator, you can just add a get method to the decorators. Add

public abstract Computer getDecorated();

to ComponentDecorator and

public Computer getDecorated(){return computer;}

to each subclass (CD, Monitor, ...). Is that what you were looking for?

like image 30
dxdpp Avatar answered Oct 13 '22 03:10

dxdpp