裝飾者模式動(dòng)態(tài)地將責(zé)任附加到對(duì)象身上。若要拓展功能,裝飾者提供了比繼承更有彈性的替代方案。
用過(guò) QQ 的人都知道, 它有很多特權(quán)服務(wù),比如說(shuō) Vip , SVip 等。我們就以此為例對(duì)裝飾者模式進(jìn)行講解。
public class User {
private String des;
public User() {
des = "I am common user";
}
public String getDes() {
return des;
}
public void function() {
System.out.println("I can use common function.");
}
}
可見(jiàn),在這里我們只是一個(gè)普通用戶,而且也只能使用普通用戶的功能。那么接下來(lái),我們想要將普通用戶升級(jí)為會(huì)員,可以使用會(huì)員功能,怎么辦呢?難道這個(gè)時(shí)候我們還要去修改 function() 中的代碼嗎?如果真是這樣,工作量真是大的難以想象。而且出于讓我們得代碼遵守開(kāi)閉原則的目的,我們不能去盲目的修改源代碼。下面我們就用裝飾者模式將普通用戶升級(jí)為 Vip 用戶。
首先,我們需要保證裝飾者和被裝飾對(duì)象有相同的超類型,所以我們現(xiàn)在將用戶寫(xiě)成一個(gè)抽象類。
public abstract class User {
public User() {
}
public String getDes() {
return "I am common user";
}
public abstract void function();
}
下面開(kāi)始書(shū)寫(xiě)裝飾對(duì)象,裝飾者可以在被裝飾者行為之前或者之后或者覆蓋原功能加上自己的行為,以達(dá)到特定的目的。下面我們也為裝飾者對(duì)象寫(xiě)一個(gè)抽象類,并讓其繼承自 User 用以保證裝飾者和被裝飾者擁有共同的父類。
public abstract class Decorator extends User {
public abstract String updateTime();
}
update() 方法用以記錄裝飾者添加到被裝飾者上的時(shí)間。下面我們就去寫(xiě)一個(gè) Vip 裝飾者,試一下功能。
public class VipDecorator extends Decorator {
private Date mDate;
private User user;
public VipDecorator(User user) {
mDate = new Date();
this.user = user;
}
@Override
public String updateTime() {
return mDate.toString();
}
@Override
public void function() {
user.function();
System.out.println("Vip function. ");
}
@Override
public String getDes() {
return "I am vip user.";
}
}
其實(shí),我們應(yīng)該在Decorator 抽象類里將 getDes() 和 function() 方法繼續(xù)聲明為抽象方法,強(qiáng)制子類實(shí)現(xiàn)這兩個(gè)方法,否則很可能會(huì)遺漏。比如我一開(kāi)始就漏寫(xiě)了 getDes() 方法。
public class Client {
public static void main(String[] args) {
User user = new CommonUser();
System.out.println(user.getDes());
user.function();
System.out.println("-------------------------");
user = new VipDecorator(user);
System.out.println(user.getDes());
user.function();
}
}
輸出結(jié)果為
I am common user
Common function.
-------------------------
I am vip user.
Common function.
Vip function.
可見(jiàn),這個(gè)時(shí)候我們想要的功能就實(shí)現(xiàn)了。而且,如果以后我們想增加其它的功能也不需要修改源代碼。比如說(shuō),現(xiàn)在我想添加 SVip.
public class SVipDecorator extends Decorator {
private Date mDate;
private User user;
public SVipDecorator(User user) {
mDate = new Date();
this.user = user;
}
@Override
public String updateTime() {
return mDate.toString();
}
@Override
public void function() {
user.function();
System.out.println("SVip function. ");
}
@Override
public String getDes() {
return "I am SVip user";
}
}
在原來(lái)的基礎(chǔ)上進(jìn)項(xiàng)測(cè)試。
public class Client {
public static void main(String[] args) {
User user = new CommonUser();
System.out.println(user.getDes());
user.function();
System.out.println("-------------------------");
user = new VipDecorator(user);
System.out.println(user.getDes());
user.function();
System.out.println("-------------------------");
user = new SVipDecorator(user);
System.out.println(user.getDes());
user.function();
}
}
打印結(jié)果為
I am common user
Common function.
-------------------------
I am vip user.
Common function.
Vip function.
-------------------------
I am SVip user
Common function.
Vip function.
SVip function.