原文地址:https://xeblog.cn/articles/15
引言
《穿越火線(xiàn)》這一游戲風(fēng)靡一時(shí),作為手游版的NC粉, 想當(dāng)年也是雄姿英發(fā)啊。好漢不提當(dāng)年勇,現(xiàn)在幾乎不怎么玩了。。。別問(wèn)我為什么,問(wèn)就是沒(méi)錢(qián),哈哈哈哈嗝~
現(xiàn)在的游戲,只要一充錢(qián),各種屬性增強(qiáng),各種坑爹特權(quán),實(shí)力再高也玩不贏RMB玩家啊,在小康路上已經(jīng)迷了路的我,不禁得說(shuō)上一句:實(shí)力不允許。

裝飾模式的定義
裝飾模式是在不必改變?cè)?lèi)文件和使用繼承的情況下,動(dòng)態(tài)地?cái)U(kuò)展一個(gè)對(duì)象的功能。它是通過(guò)創(chuàng)建一個(gè)包裝對(duì)象,也就是裝飾來(lái)包裹真實(shí)的對(duì)象。
對(duì)于網(wǎng)癮少年來(lái)說(shuō),就是游戲里的皮膚,讓游戲里的角色、武器啥的變得好看的。
裝飾模式的通用類(lèi)圖:

-
Component
Component是一個(gè)接口或者抽象類(lèi),它定義一個(gè)最核心的對(duì)象,是一個(gè)最原始的業(yè)務(wù)場(chǎng)景。 -
ConcreteComponent
ConcreteComponent是最核心、最原始的業(yè)務(wù)邏輯實(shí)現(xiàn),要裝飾的就是它。 -
Decorator
顧名思義,它是一個(gè)專(zhuān)門(mén)做裝飾的類(lèi),說(shuō)白了,就是一個(gè)裝修工。它一般是一個(gè)抽象類(lèi),也需要實(shí)現(xiàn)最原始的業(yè)務(wù)邏輯,不同于其它實(shí)現(xiàn)類(lèi)的是,它需要定義一個(gè)private變量指向Component對(duì)象,一般通過(guò)構(gòu)造的方式傳入Component對(duì)象。 -
ConcreteComponentA、ConcreteComponentB
它們是兩個(gè)具體的裝飾類(lèi),通過(guò)這兩個(gè)裝飾類(lèi)來(lái)增強(qiáng)或減弱原始的業(yè)務(wù)邏輯,再說(shuō)白了,就是游戲里的兩個(gè)皮膚,給原先角色或武器裝飾上后,別提多NB了。

裝飾模式的實(shí)現(xiàn)
首先定義一個(gè)具體的業(yè)務(wù)游戲場(chǎng)景,CF游戲中的最基本的操作:登入、開(kāi)火、丟手雷
UML類(lèi)圖

抽象構(gòu)件:CFGameService
/**
* cf游戲服務(wù)接口
*
* @author anlingyi
*/
public interface CFGameService {
/**
* 登入
* @param username
* @param password
*/
void login(String username, String password);
/**
* 開(kāi)槍射擊
*/
void fire();
/**
* 丟手雷
*/
void grenade();
}
具體構(gòu)件:CFerServiceImpl
/**
* cf游戲者實(shí)現(xiàn)類(lèi)
*
* @author anlingyi
*/
public class CFerServiceImpl implements CFGameService {
@Override
public void login(String username, String password) {
System.out.println(username + ", 登入游戲成功!");
}
@Override
public void fire() {
System.out.println("開(kāi)火。。。");
}
@Override
public void grenade() {
System.out.println("丟雷。。。");
}
}
抽象裝飾者:CFGameDecorator
/**
* cf游戲裝飾類(lèi)
*/
public abstract class CFGameDecorator implements CFGameService {
/**
* 被裝飾的對(duì)象
*/
private CFGameService cfGameService;
/**
* 通過(guò)構(gòu)造函數(shù)傳遞被修飾對(duì)象
* @param cfGameService
*/
public CFGameDecorator(CFGameService cfGameService) {
this.cfGameService = cfGameService;
}
@Override
public void login(String username, String password) {
this.cfGameService.login(username, password);
}
@Override
public void fire() {
this.cfGameService.fire();
}
@Override
public void grenade() {
this.cfGameService.grenade();
}
}
具體的裝飾類(lèi):ArmsDecorator、EffectDecorator
/**
* 武器裝飾類(lèi)
*
* @author anlingyi
*/
public class ArmsDecorator extends CFGameDecorator {
public ArmsDecorator(CFGameService cfGameService) {
super(cfGameService);
}
@Override
public void fire() {
// 增強(qiáng)武器
this.useFirearms();
super.fire();
}
@Override
public void grenade() {
// 增強(qiáng)手雷
this.useGrenade();
super.grenade();
}
/**
* 增強(qiáng)武器的方法
*/
private void useFirearms() {
System.out.println("裝備:AK-47-火麒麟");
}
/**
* 增強(qiáng)手雷的方法
*/
private void useGrenade() {
System.out.println("裝備:高爆手雷");
}
}
/**
* 效果裝飾類(lèi)
*
* @author anlingyi
*/
public class EffectDecorator extends CFGameDecorator {
public EffectDecorator(CFGameService cfGameService) {
super(cfGameService);
}
@Override
public void login(String username, String password) {
// vip會(huì)員
System.out.println("尊貴的vvvvvip會(huì)員");
super.login(username, password);
}
@Override
public void fire() {
super.fire();
// 增加擊殺音效
this.killSound();
}
@Override
public void grenade() {
super.grenade();
// 增加丟手雷音效
this.grenadeSound();
}
/**
* 增加擊殺音效
*/
private void killSound() {
System.out.println("嘿帥!");
}
/**
* 增加丟手雷的音效
*/
private void grenadeSound() {
System.out.println("發(fā)呀的轟!");
}
}
開(kāi)始游戲
平民玩家進(jìn)入了游戲。。。
/**
* cf客戶(hù)端
*
* @author anlingyi
*/
public class CFClient {
public static void main(String[] args) {
CFGameService cf = new CFerServiceImpl();
cf.login("小毅", "123456");
cf.fire();
cf.grenade();
}
}
游戲效果:
小毅, 登入游戲成功!
開(kāi)火。。。
丟雷。。。
毫無(wú)樂(lè)趣可言。

“這個(gè)問(wèn)題充錢(qián)就能解決” —— 老子(子讀一聲)
RMB玩家進(jìn)入了游戲。。。
/**
* cf客戶(hù)端
*
* @author anlingyi
*/
public class CFClient {
public static void main(String[] args) {
CFGameService cf = new CFerServiceImpl();
// 充錢(qián)充錢(qián)(修飾武器)
cf = new ArmsDecorator(cf);
cf.login("小毅", "123456");
cf.fire();
cf.grenade();
}
}
游戲效果:
小毅, 登入游戲成功!
裝備:AK-47-火麒麟
開(kāi)火。。。
裝備:高爆手雷
丟雷。。。
瞬間NB多了,連隔壁小孩都饞哭了。。。哈哈哈~

繼續(xù)充
/**
* cf客戶(hù)端
*
* @author anlingyi
*/
public class CFClient {
public static void main(String[] args) {
CFGameService cf = new CFerServiceImpl();
// 充錢(qián)充錢(qián)(修飾武器)
cf = new ArmsDecorator(cf);
// 再充(修飾效果)
cf = new EffectDecorator(cf);
cf.login("小毅", "123456");
cf.fire();
cf.grenade();
}
}
游戲效果:
尊貴的vvvvvip會(huì)員
小毅, 登入游戲成功!
裝備:AK-47-火麒麟
開(kāi)火。。。
嘿帥!
裝備:高爆手雷
丟雷。。。
發(fā)呀的轟!
越充越NB,越NB越好玩,越好玩越充。。。從此,在貧困的道路上越走越遠(yuǎn)。

裝飾模式的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
- 裝飾類(lèi)和被裝飾類(lèi)可以獨(dú)立發(fā)展,而不會(huì)相互耦合。
Component類(lèi)不需要知道Decorator類(lèi)的存在,Decorator類(lèi)是從外部來(lái)擴(kuò)展Component類(lèi)的功能,而Decorator類(lèi)也不用知道具體的構(gòu)件。 - 裝飾模式是繼承關(guān)系的一個(gè)替代方案,裝飾對(duì)象和真實(shí)對(duì)象具有相同的接口。
- 裝飾模式可以動(dòng)態(tài)地?cái)U(kuò)展一個(gè)實(shí)現(xiàn)類(lèi)的功能,不用修改原有對(duì)象的結(jié)構(gòu)就可以增強(qiáng)或減弱原有的功能。
缺點(diǎn)
- 過(guò)度的使用裝飾模式會(huì)使程序變得更加復(fù)雜。
資源
參考
- 《設(shè)計(jì)模式之禪》