2012-09-02 144 views
2

我在閱讀「傻瓜設計模式」。我閱讀並練習裝飾模式。使用裝飾模式,我們可以用任何東西裝飾物體。現在,我想在裝飾之前刪除裝飾對象。我通過ArrayList解決了這個問題,但我仍然覺得它不好。你能告訴我如何刪除裝飾對象嗎?什麼是更好的方法?如何從裝飾模式中刪除裝飾對象Java中的模式

這是我的方式:

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

回答

1

我懷疑我誤解你的問題,但Ť o將裝飾(內部)對象從裝飾器中取出,只需向裝飾器添加get方法即可。添加

public abstract Computer getDecorated();

到ComponentDecorator和

public Computer getDecorated(){return computer;}

到每個子類(CD,監視器,...)。那是你在找什麼?

+0

對不起,我不擅長英語。這意味着我裝飾一個對象,我想刪除之前已裝飾的對象。例如:我有一臺電腦,然後將它添加到硬盤,屏幕和CD驅動器。但過了一會兒,我取下了CD驅動器,而我的電腦只有顯示器和硬盤驅動器。設備隨機刪除和選項。 我正在尋找這個問題的最佳解決方案 –

+0

感謝您的答案,但我不想要裝飾對象。當我刪除裝飾器之前,我想獲取裝飾對象。 公共計算機getDecorated(){回報計算機;} 該方法返回一個裝飾物,這是沒有必要的,因爲構造函數是已經在做了 –

+0

裝飾對象/去除裝飾對象...你能告訴我一個更好的方法是什麼? –

6

更好的方法是將「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類擴展ComponentDecorator而不是其他方法。

+0

你可以發佈你的編輯代碼嗎? –

1

添加兩種方法的接口,去除裝飾()和removeDecoration(字符串的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<String> 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

裝飾鏈去除後基本串飾,花式

拆除裝修:基本字符串,花式。

+0

在這一點上,雖然......不是你比裝飾者更像攔截器嗎? –