裝飾模式的java實現例子
阿新 • • 發佈:2019-01-25
說明:本文是《大話設計模式》一書的學習文摘和網上相關資訊文摘,原書程式碼例子用C#寫,下面用Java改寫。
1、裝飾模式:在不必改變原類檔案和使用繼承的情況下,動態地擴充套件一個物件的功能。它是通過建立一個包裝物件,也就是裝飾來包裹真實的物件。
2、裝飾模式由4種角色組成:
(1)抽象構件(Component)角色:給出一個抽象介面,以規範準備接收附加職責的物件。
(2)具體構件(Concrete Component)角色:定義一個將要接收附加職責的類。
(3)裝飾(Decorator)角色:持有一個構件(Component)物件的例項,並實現一個與抽象構件介面一致的介面,從外類來擴充套件Component類的功能,但對於Component類來說,是無需知道Decorato的存在的。
(4)具體裝飾(Concrete Decorator)角色:負責給構件物件新增上附加的職責。
3、裝飾模式的UML類圖
4、裝飾模式的特點
(1)裝飾物件和真實物件有相同的介面。這樣客戶端物件就能以和真實物件相同的方式和裝飾物件互動。
(2)裝飾物件包含一個真實物件的引用。
(3)裝飾物件接受所有來自客戶端的請求。它把這些請求轉發給真實的物件。
(4)裝飾物件可以在轉發這些請求以前或以後增加一些附加功能。這樣就確保了在執行時,不用修改給定物件的結構就可以在外部增加附加的功能。在面向物件的設計中,通常是通過繼承來實現對給定類的功能擴充套件。
5、適用性
(1)需要擴充套件一個類的功能,或給一個類新增附加職責。
(2)需要動態的給一個物件新增功能,這些功能可以再動態的撤銷。
(3)需要增加由一些基本功能的排列組合而產生的非常大量的功能,從而使繼承關係變的不現實。
(4)當不能採用生成子類的方法進行擴充時。一種情況是,可能有大量獨立的擴充套件,為支援每一種組合將產生大量的子類,使得子類數目呈爆炸性增長。另一種情況可能是因為類定義被隱藏,或類定義不能用於生成子類。
6、模式簡化
(1)如果只有一個Concrete Component類而沒有抽象的Component介面時,可以讓Decorator繼承Concrete Component。
(2)如果只有一個Concrete Decorator類時,可以將Decorator和Concrete Decorator合併。
7、程式碼實現
package demo4; /** * 抽象構件角色 */ public abstract class Component { public abstract void operation(); } package demo4; /** * 具體構件角色 */ public class ConcreteComponent extends Component { @Override public void operation() { System.out.println("具體物件的操作"); } } package demo4; /** * 裝飾角色 */ public abstract class Decorator extends Component { protected Component component; public void setComponent(Component component){ this.component = component; } @Override public void operation() { if(component != null){ component.operation(); } } } package demo4; /** * 具體裝飾角色A */ public class ConcreteDecoratorA extends Decorator { //本類的獨有功能 private String addedState; //首先執行原Component的operation(),再執行本類的功能,相當於對原Component進行了裝飾 @Override public void operation(){ super.operation(); addedState = "New State"; System.out.println("具體裝飾物件A的操作。" + addedState); } } package demo4; /** * 具體裝飾角色B */ public class ConcreteDecoratorB extends Decorator { //首先執行原Component的operation(),再執行本類的功能,相當於對原Component進行了裝飾 @Override public void operation() { super.operation(); AddedBehavior(); System.out.println("具體裝飾物件B的操作"); } //本類的獨有功能 private void AddedBehavior() { System.out.println("我是具體裝飾物件B的獨有方法"); } } package demo4; /** * 客戶端程式碼 */ public class Demo4 { public static void main(String[] args) { ConcreteComponent c = new ConcreteComponent(); ConcreteDecoratorA d1 = new ConcreteDecoratorA(); ConcreteDecoratorB d2 = new ConcreteDecoratorB(); d1.setComponent(c); d2.setComponent(d1); d2.operation(); /*執行輸出結果: 具體物件的操作 具體裝飾物件A的操作。New State 我是具體裝飾物件B的獨有方法 具體裝飾物件B的操作 */ } }
8、一個例子:給人搭配不同的服飾
package demo5;
/**
*“Person”類(ConcreteComponent)
*/
public class Person {
public Person() {
}
private String name;
public Person(String name){
this.name = name;
}
public void show(){
System.out.println(String.format("裝扮的%s", name));
}
}
package demo5;
/**
* 服飾類(Decorator)
*/
public class Finery extends Person {
protected Person component;
public void decorate(Person component) {
this.component = component;
}
@Override
public void show() {
if(component != null){
component.show();
}
}
}
package demo5;
/**
* 具體服飾類(ConcreteDecorator)
*/
public class TShirts extends Finery {
@Override
public void show() {
System.out.println("大T恤");
super.show();
}
}
package demo5;
/**
* 具體服飾類(ConcreteDecorator)
*/
public class Sneakers extends Finery {
@Override
public void show() {
System.out.println("球鞋");
super.show();
}
}
package demo5;
/**
* 具體服飾類(ConcreteDecorator)
*/
public class BigTrouser extends Finery {
@Override
public void show() {
System.out.println("垮褲");
super.show();
}
}
package demo5;
/**
* 客戶端程式碼
*/
public class Demo5 {
public static void main(String[] args) {
Person xc = new Person("小菜");
Sneakers pqx = new Sneakers();
BigTrouser kk = new BigTrouser();
TShirts dtx = new TShirts();
pqx.decorate(xc);
kk.decorate(pqx);
dtx.decorate(kk);
dtx.show();
/*
執行結果:
大T恤
垮褲
球鞋
裝扮的小菜
*/
}
}