裝飾器模式(Decorator Pattern)
裝飾器模式可用來給一個類動態添加功能,將其裝飾成一個新的類。這就是裝飾器的概念。看到這里我們可能會想,要達到這種效果,我們用子類繼承父類不就可以了嗎? 沒錯裝飾器模式,本身是一種繼承的替代方案。那既然是替代方案,那么自然就有它不一樣的地方。
具體區別在哪里呢? 請看
- 裝飾器模式更靈活:繼承時父子類的關系是靜態的,而裝飾器模式是動態的,裝飾類和被裝飾類的關系是運行時候確認的
- 裝飾類和被裝飾類的耦合關系是松散的,各自可以獨立變化
下面看看具體的代碼。具體過程可看注釋
// 1.首先我們有一個Pen接口 public interface Pen { public void write(); } // 2.Pencil類實現了Pen這個接口 public class Pencil implements Pen { public void write () { System.out.print("寫"); } } // 3.裝飾類PencilDecorator也實現了Pen這個接口,且代理調用Pencil的方法 public class PencilDecorator implements Pen{ Pen pen; public PencilDecorator(Pen pen) { this.pen = pen; } public void write () { pen.write(); } } // 4.用具體裝飾類繼承PencilDecorator,這樣就可以做擴展變化 public class BluePencilDecorator extends PencilDecorator{ public BluePencilDecorator (Pen pen) { super(pen); } public void writeBlue () { this.write(); System.out.println("寫出來是藍色的"); } } // 同4.用具體裝飾類繼承PencilDecorator,這樣就可以做擴展變化 public class RedPencilDecorator extends PencilDecorator{ public RedPencilDecorator (Pen pen) { super(pen); } public void writeRed () { this.write(); System.out.println("寫出來是紅色的"); } } // 測試 public class Test { public static void main(String args []) { Pen pencil = new Pencil(); RedPencilDecorator redPencil = new RedPencilDecorator(pencil); BluePencilDecorator bluePencil = new BluePencilDecorator(pencil); redPencil.writeRed(); bluePencil.writeBlue(); } }
輸出結果

代碼的結構如下圖所示

從這里我們看到了,經過PencilDecorator類這一層的隔離,Pencil類和BluePencilDecorator類/RedPencilDecorator類在一定程度上解耦,從而各自獨立發展了。這就是代理模式能夠替代繼承的原因和它的獨特優勢
唉!! 等一下,好像看到了什么熟悉的東西,請看


沒錯,這還真就是代理模式的代碼。
在這里,我們可以從兩個角度去理解裝飾器模式。
- 第一,從構成上看,裝飾器模式 = 代理模式 + 類繼承。 也就是在代理模式的基礎上,加了一堆繼承[代理類]的子類,從而進行擴展變化,並且還盡量減少了和原有類的聯系。
- 第二,從功能上看,代理模式側重的是“控制”,而裝飾器模式側重的是“擴展”。比如說,類A代理了類B,那么這兩個類由於同一個接口的約束,它們的方法和實現的功能其實是一樣的。而類C裝飾了類D,那么這個時候類C不僅僅具備了類D的方法,同時還能加入自己的特殊邏輯。
中介者模式(Mediator Pattern)
簡單的說,中介者模式是一個分散到集中的一個過程

還是看下具體的代碼
// Colleague接口 public interface Colleague { public void handleExternal(Mediator mediator); public void handleInternal(); } // 中介者接口 public abstract class Mediator { public Colleague A; public Colleague B; public Colleague C; public Mediator (Colleague A, Colleague B, Colleague C) { super(); this.A = A; this.B = B; this.C = C; } public abstract void handleA (); public abstract void handleB (); public abstract void handleC (); } // 實現了中介者接口的中介者類,封裝了不同Colleague類的對象間的復雜操作 public class ConcreteMediator extends Mediator{ public ConcreteMediator(Colleague A, Colleague B, Colleague C) { super(A,B,C); } public void handleA() { B.handleInternal(); C.handleInternal(); } public void handleB() { A.handleInternal(); C.handleInternal(); } public void handleC() { A.handleInternal(); B.handleInternal(); } } // Colleague類在涉及其他Colleague類的復雜操作的時候,通過中介者調用 public class A implements Colleague { public void handleExternal(Mediator mediator) { mediator.handleA(); System.out.println("---------------"); } public void handleInternal() { System.out.println("A"); } } // Colleague類在涉及其他Colleague類的復雜操作的時候,通過中介者調用 public class B implements Colleague { public void handleExternal(Mediator mediator) { mediator.handleB(); System.out.println("---------------"); } public void handleInternal() { System.out.println("B"); } } // Colleague類在涉及其他Colleague類的復雜操作的時候,通過中介者調用 public class C implements Colleague { public void handleExternal(Mediator mediator) { mediator.handleC(); System.out.println("---------------"); } public void handleInternal() { System.out.println("C"); } } // 測試 public class main { public static void main(String args []) { Colleague a = new A(); Colleague b = new B(); Colleague c = new C(); Mediator mediator = new ConcreteMediator(a,b,c); a.handleExternal(mediator); b.handleExternal(mediator); c.handleExternal(mediator); } }
結果輸出

中介者模式理解起來,就好像
- 你有很多雜亂的物品擺放在房間的不同地方,找起來很不好找,現在把這些物品統一放到一個櫃子里,方便集中管理。
- 一群人去食堂打飯的時候,如果各自去取菜那么食堂可能亂做一團,所以這時候食堂大媽就成為了“中介者”
原型模式(Prototype Pattern)
原型模式是什么?
一句話,原型模式就是克隆對象,完了。
這么簡單? 這也能叫設計模式?

沒錯,就是這樣
讓我們看下代碼
// 通過實現Cloneable接口並重寫clone方法的方式,讓Bar對象變得可克隆。 public class Bar implements Cloneable { String value; public String getValue () { return value; } public void setValue (String value) { this.value = value; } public Bar clone() { Bar clone = null; try { clone = (Bar)super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return clone; } } // 調用clone方法可以克隆對象 public class mian { public static void main(String args []) { Bar bar = new Bar(); Bar bar2 = bar.clone(); bar.setValue("1"); bar2.setValue("2"); System.out.println(bar.getValue()); System.out.println(bar2.getValue()); } }
運行結果

告訴我,原型模式的本質是什么
原型模式的本質就是—— 套娃

原型模式的優缺點
- 原型模式的優點: 底層的二進制實現拷貝,相比起new操作可以節約性能
- 原型模式的缺點: 構造函數沒有調用,犧牲了靈活性