巧妙的運(yùn)用裝飾器,讓你的代碼高出一個(gè)逼格!
一、介紹
裝飾器模式,顧名思義,就是在一個(gè)類上增加功能,以起到裝飾的作用。
我們都知道,如果想給某個(gè)類新增功能,但又要避免在原類上修改代碼,最常用的方式就是新增一個(gè)類來繼承目標(biāo)類,但是如果增加多的話,會(huì)使類的數(shù)量爆炸式增長,為管理帶來巨大的麻煩,裝飾器模式就比較好地解決了這一點(diǎn)。
從設(shè)計(jì)的角度看,裝飾器模式涉及到四個(gè)角色:
- 被裝飾類:要進(jìn)行擴(kuò)展的源類;
- 裝飾器類:通過該類可以給被裝飾類動(dòng)態(tài)添加額外的方法,多以抽象為主;
- 具體的裝飾類:該類實(shí)現(xiàn)自裝飾器類,已完成完整的算法;
- 客戶角色:客戶類提出使用具體類的請求;
今天我們一起來看看深度了解一下裝飾器的玩法!
二、代碼示例
下面以生產(chǎn)一件衣服為例,一塊布料裁剪好了之后做出的衣服樣子還可以,但是這樣的衣服是賣不出去的,因?yàn)楹翢o美感,因此我們需要通過一些裝飾來使衣服變得好看。
我們先來創(chuàng)建一個(gè)抽象類或者接口,定義一個(gè)骨架,如下:
- /**
- * 建立基本骨架
- */
- public interface Clothes {
- void makeClothes();
- }
接著創(chuàng)建一個(gè)我們需要裝飾的源類,如下:
- /**
- * 被裝飾類
- */
- public class MakeClothes implements Clothes {
- @Override
- public void makeClothes() {
- System.out.println("制作一件衣服");
- }
- }
再來創(chuàng)建我們的主角,裝飾類,如下:
- /**
- * 裝飾類
- */
- public class Decorator implements Clothes {
- private Clothes clothes;
- public Decorator(Clothes clothes) {
- this.clothes = clothes;
- }
- @Override
- public void makeClothes() {
- clothes.makeClothes();
- }
- }
最后,分別創(chuàng)建兩個(gè)具體的裝飾類,如下:
- /**
- * 具體的裝飾類
- */
- public class EmbroideryDecorator extends Decorator {
- public EmbroideryDecorator(Clothes clothes) {
- super(clothes);
- }
- @Override
- public void makeClothes() {
- super.makeClothes();
- System.out.println("給衣服繡制花朵");
- }
- }
- /**
- * 具體的裝飾類
- */
- public class MickeyDecorator extends Decorator {
- public MickeyDecorator(Clothes clothes) {
- super(clothes);
- }
- @Override
- public void makeClothes() {
- super.makeClothes();
- System.out.println("給衣服繪制米老鼠圖案");
- }
- }
怎么用呢?請看下面的測試類:
- /**
- * 客戶端
- */
- public class DecorateClient {
- public static void main(String[] args) {
- Clothes clothes = new MakeClothes();
- clothes = new EmbroideryDecorator(clothes);//給衣服繡花
- clothes = new MickeyDecorator(clothes);//給衣服添加米老鼠圖案
- clothes.makeClothes();
- System.out.println("成品已經(jīng)完成!");
- }
- }
輸出結(jié)果如下:
- 制作一件衣服
- 給衣服繡制花朵
- 給衣服繪制米老鼠圖案
- 成品已經(jīng)完成
制作一件衣服給衣服繡制花朵給衣服繪制米老鼠圖案成品已經(jīng)完成
從結(jié)果上,可以看到,我們成功的給MakeClothes這個(gè)類,動(dòng)態(tài)添加了2個(gè)方法,一個(gè)是給衣服繡花,另一個(gè)是給衣服添加米老鼠圖案,最后成品完成!
可見裝飾的效果還不錯(cuò)~
三、應(yīng)用
其實(shí)在 jdk 中,裝飾者設(shè)計(jì)模式也有很多典型的場景應(yīng)用,例如我們熟悉的io包中的字節(jié)輸入、輸出流,就用到了裝飾者設(shè)計(jì)模式!
其中FilterInputStream、FilterOutputStream就是裝飾類,用于動(dòng)態(tài)給輸入、輸出流增加方法!
四、總結(jié)
巧妙采用裝飾器模式,可以很好的解決類繼承數(shù)量過多的問題,讓代碼清晰可讀。
但是如果裝飾層數(shù)過多,也會(huì)影響到代碼的維護(hù),因此在實(shí)際的使用過程中,還需靈活使用!