裝飾器模式(Decorator)

原文鏈接:https://www.cnblogs.com/zhangtianq/p/6091047.html

職責:動態的爲一個對象增加新的功能

   裝飾器模式是一種用於代替繼承的技術,無需通過繼承增加子類就能擴展對象的新功能。使用對象的關聯關係代替繼承關係,更加靈活,同時避免類型體系的快速膨脹。


實現細節:

——Component抽象構件角色:真實對象和裝飾對象有相同的接口。這樣,客戶端對象就能夠以與真實對象相同的方式同裝飾對象交互。

——ConcreteComponent具體構件角色(真實對象):io流中的FileInputStream、    FileOutputStream

——Decorator裝飾角色:持有一個抽象構件的引用。裝飾對象接受所有客戶端的請求,並把這些請求轉發給真實的對象。這樣,就能在真實對象調用前後增加新的功能。

——ConcreteDecorator具體裝飾角色:負責給構件對象增加新的責任。


 開發中的使用場景:

  IO中輸入流和輸出流的設計

  Swing包中圖形界面構件功能

  Servlet API中提供了一個request對象的Decorator設計模式的默認實現類HttpServletRequestWrapper,HttpServletRequestWrapper類增強了request對象的功能。

  Struts2中,request,response,session對象的處理


 

1. 創建一個抽象組件ICar接口,並創建具體構建角色以及各個具體裝飾角色

複製代碼
 1 package com.ztq.decorator;
 2 
 3 /***
 4  * 抽象組件
 5  * @author ZTQ
 6  *
 7  */
 8 public interface ICar {
 9     void move();
10 }
11 
12 //ConcreteComponent 具體構件角色(真實對象)
13 class Car implements ICar{
14 
15     @Override
16     public void move() {
17         System.out.println("陸地上跑!");
18     }
19     
20 }
21 
22 class SuperCar implements ICar{
23     private ICar car;
24     public SuperCar(ICar car){
25         this.car = car;
26     }
27     
28     @Override
29     public void move() {
30         car.move();
31     }
32     
33 }
34 
35 //ConcreteDecorator具體裝飾角色
36 class FlyCar extends SuperCar{
37 
38     public FlyCar(ICar car) {
39         super(car);
40     }
41     
42     public void fly(){
43         System.out.println("天上飛");
44     }
45     
46     @Override
47     public void move() {
48         super.move();
49         fly();
50     }
51 }
52 
53 //ConcreteDecorator具體裝飾角色
54 class WaterCar extends SuperCar{
55 
56     public WaterCar(ICar car) {
57         super(car);
58     }
59     
60     public void swim(){
61         System.out.println("水裏遊");
62     }
63     
64     @Override
65     public void move() {
66         super.move();
67         swim();
68     }
69 }
70 
71 //ConcreteDecorator具體裝飾角色
72 class AICar extends SuperCar{
73 
74     public AICar(ICar car) {
75         super(car);
76     }
77     
78     public void autoMove(){
79         System.out.println("自動跑");
80     }
81     
82     @Override
83     public void move() {
84         super.move();
85         autoMove();
86     }
87 }
複製代碼

 

2. 創建測試類Client

複製代碼
 1 package com.ztq.decorator;
 2 
 3 public class Client {
 4     public static void main(String[] args) {
 5         Car car = new Car();
 6         car.move();
 7         
 8         System.out.println("增加新的功能:飛行");
 9         FlyCar flycar = new FlyCar(car);
10         flycar.move();
11         
12         System.out.println("增加新的功能:水裏遊");
13         WaterCar waterCar = new WaterCar(car);
14         waterCar.move();
15         
16         System.out.println("增加兩個新的功能,飛行,水裏遊");
17         WaterCar waterCar2 = new WaterCar(new FlyCar(car));
18         waterCar2.move();
19     }
20 }
複製代碼

 

結果:

複製代碼
陸地上跑!
增加新的功能:飛行
陸地上跑!
天上飛
增加新的功能:水裏遊
陸地上跑!
水裏遊
增加兩個新的功能,飛行,水裏遊
陸地上跑!
天上飛
水裏遊
複製代碼

 

UML圖:

 


 

總結:

  裝飾模式(Decorator)也叫包裝器模式(Wrapper)

  裝飾模式降低系統的耦合度,可以動態的增加或刪除對象的職責,並使得需要裝飾的具體構建類和具體裝飾類可以獨立變化,以便增加新的具體構建類和具體裝飾類。

  優點:

  • 擴展對象功能,比繼承靈活,不會導致類個數急劇增加
  • 可以對一個對象進行多次裝飾,創造出不同行爲的組合,得到功能更加強大的對象
  • 具體構建類和具體裝飾類可以獨立變化,用戶可以根據需要自己增加新的具體構件子類和具體裝飾子類

  缺點:

  • 產生很多小對象。大量小對象佔據內存,一定程度上影響性能
  • 裝飾模式易於出錯,調試排查比較麻煩

 

裝飾模式和橋接模式的區別:

兩個模式都是爲了解決過多子類對象問題。但他們的誘因不一樣。橋接模式是對象自身現有機制沿着多個維度變化,是既有部分不穩定。裝飾模式是爲了增加新的功能。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章