如何从Java中的Decorator Pattern中删除装饰对象

我正在读“傻瓜设计模式”。 我阅读并练习了装饰模式。 使用Decorator Pattern,我们可以用任何东西装饰一个对象。 现在,我想在装饰之前删除装饰对象。我已经通过ArrayList解决了这个问题,但我仍觉得它不好。 你能告诉我如何删除装饰物吗? 什么是更好的方法?

这是我的方式:

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 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; } } 

一种更好的方法是将“removeDecorator”方法添加到ComponentDecorator类中。

 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()); } 

}

如果您没有要删除的装饰器的引用,则可以创建另一个类而不是类。

但是,您需要将装饰对象设置为“ComponentDecorator”而不是“Computer”。 我建议让Computer类扩展ComponentDecorator而不是相反。

我怀疑我误解了你的问题,但是要将装饰的(内部)对象从装饰器中取出,你可以向装饰器添加一个get方法。 加

public abstract Computer getDecorated();

到ComponentDecorator和

public Computer getDecorated(){return computer;}

到每个子类(CD,监视器,……)。 那是你在找什么?

向接口添加两个方法,undecorate()和removeDecoration(String className):

ThingInterface.java

 public interface ThingInterface { public ThingInterface undecorate(); public ThingInterface removeDecoration(String className); public String nonDecoratedString(); public String decoratedString(); } 

您的基类将仅为这些方法返回自己:

BaseThing.java

 public class BaseThing implements ThingInterface { private String basicString; public BaseThing(String string) { basicString = string; } @Override public ThingInterface undecorate() { return this; } @Override public ThingInterface removeDecoration(String className) { return this; } @Override public String nonDecoratedString() { return basicString; } @Override public String decoratedString() { return basicString; } } 

现在你需要的真正的东西是抽象类:

AbstractThingDecorator.java

 public abstract class AbstractThingDecorator implements ThingInterface { private ThingInterface thing; public AbstractThingDecorator(ThingInterface thing) { this.thing = thing; } @Override public ThingInterface removeDecoration(String className) { ThingInterface undecorate = this; if(this.getClass().getName() == className) { undecorate = this.undecorate(); } else { ArrayList classStack = new ArrayList(); while(undecorate != undecorate.undecorate()) { if(undecorate.getClass().getName() != className) { classStack.add(undecorate.getClass().getName()); } undecorate = undecorate.undecorate(); } for(int i = classStack.size()-1;i == 0;i--) { try { Class clazz = Class.forName(classStack.get(i)); Constructor ctor = clazz.getConstructor(ThingInterface.class); Object object = ctor.newInstance(new Object[] { undecorate }); undecorate = (ThingInterface) object; } catch(Exception e) { System.out.println("Exception:" + e.getMessage()); } } } return undecorate; } @Override public ThingInterface undecorate() { return this.thing; } @Override public String nonDecoratedString() { return thing.nonDecoratedString(); } @Override public String decoratedString() { return thing.decoratedString(); } } 

我正在添加两个简单的装饰器,ThingDecorator和FancyThingDecorator:

ThingDecorator.java

 public class ThingDecorator extends AbstractThingDecorator { public ThingDecorator(ThingInterface thing) { super(thing); } @Override public ThingInterface undecorate() { return super.undecorate(); } @Override public String decoratedString() { return super.decoratedString() + ", decorated"; } } 

FancyThingDecorator.java

 public class FancyThingDecorator extends AbstractThingDecorator { public FancyThingDecorator(ThingInterface thing) { super(thing); } @Override public ThingInterface undecorate() { return super.undecorate(); } @Override public String decoratedString() { return super.decoratedString() + ", fancy"; } } 

最后,我的java主要:

Decorator.java

 public class Decorator { /** * @param args */ public static void main(String[] args) { ThingInterface thing = new BaseThing("Basic string"); ThingInterface decorator = new ThingDecorator(thing); ThingInterface fancyDecorator = new FancyThingDecorator(thing); ThingInterface extraFancy = new FancyThingDecorator(new ThingDecorator(thing)); ThingInterface undecorate = new FancyThingDecorator(new ThingDecorator(thing)); System.out.println("Basic thing is: " + thing.decoratedString()+"."); System.out.println("Decorated thing is: " + decorator.decoratedString()+"."); System.out.println("Fancy thing is: " + fancyDecorator.decoratedString()+"."); System.out.println("Decorated fancy thing is: " + extraFancy.decoratedString()+"."); while(extraFancy.undecorate() != extraFancy) { extraFancy = extraFancy.undecorate(); System.out.println("Rolling back decorations: " + extraFancy.decoratedString()+"."); } System.out.println("Decoration chain before removal is: " + undecorate.decoratedString()); System.out.println("Removing decoration for " + ThingDecorator.class.getName()); undecorate = undecorate.removeDecoration(ThingDecorator.class.getName()); System.out.println("Decoration chain after removal is: " + undecorate.decoratedString()+"."); } } 

输出是:

基本的东西是:基本字符串。

装饰的东西是:基本字符串,装饰。

花哨的是:基本字符串,花哨。

装饰花哨的东西是:基本的字符串,装饰,花哨。

回滚装饰:基本字符串,装饰。

回滚装饰:基本字符串。

拆卸前的装饰链是:基本字符串,装饰,花式

删除ThingDecorator的装饰

拆除后的装饰链是:基本字符串,花式。