1. 程式人生 > >大話設計模式之裝飾模式

大話設計模式之裝飾模式

   

    經過了前面的設計原則和工廠三姐妹、單例設計模式的學習,我相信大家已經掌握了基本的學習方法,今天我們來總結裝飾模式,首先來看一下裝飾模式的UML圖:

                     

    接著我們根據UML圖寫一下原始碼實現:

 abstract class Component{
        public abstract void Operation();
    }
    public class ConcreteComponent extends Component{

        @Override
        public void Operation()
        {
            System.out.println("The orinal operation");
        }
        
    }
    public class Decorator extends Component{
        protected Component component;
        public void SetComponent(Component component){
            this.component = component;
        }

        @Override
        public void Operation()
        {
            if(component !=null){
                component.Operation();  //super operation
            }
        }
        
    }
    public class ConcreteDecoratorA extends Decorator{
        private String addedState ;//
        @Override
        public void Operation()
        {
            super.Operation();
            addedState = "The new decorator field";
            System.out.println("decorator new field");
        }
        
    }
    public class ConcreteDecoratorB extends Decorator{
        private void AddedBehavior(){
            System.out.println("decorator new method");
        }
        @Override
        public void Operation()
        {
            super.Operation();
            AddedBehavior();
        }
    }

    裝飾模式的關鍵在於裝飾類利用SetComponent來對被裝飾的物件進行包裝,這樣每個裝飾物件的實現就和如何使用這個物件分離開了,每個裝飾物件只關心自己的功能,不需要關心如何被新增到物件鏈當中。客戶端程式碼如下:

public void main(String[] args){
        ConcreteComponent c = new ConcreteComponent();
        ConcreteDecoratorA d1 = new ConcreteDecoratorA();
        ConcreteDecoratorB d2 = new ConcreteDecoratorB();
        d1.SetComponent(c);
        d2.SetComponent(d1);
        d2.Operation();
    }

    原本的類C,我們首先使用d1對其進行裝飾,然後使用d2去裝飾d1,實現效果就是在c的基礎上添加了新的欄位和一個新的方法。   

    好了,上面就是裝飾模式的原始碼了,可能有些晦澀了,接下來我們使用一個生活中的小例子去解釋一下裝飾模式。

    我們每天早上吃早飯都吃什麼呢?像我的最愛就是煎餅了,接下來,我們就以煎餅為例子來解釋一下裝飾模式。煎餅真是無慾則鋼有容乃大,我們可以在原味煎餅的基礎上去加烤腸、辣條、生菜、雞柳等。那麼我們試著用裝飾模式試著去描述一下這個過程吧:

abstract class Jianbing{
        public abstract void Operation();
    }
    //原味煎餅
    public class Yuanweijianbing extends Jianbing{

        @Override
        public void Operation()
        {
            System.out.println("原味煎餅");
        }
        
    }
   //加料煎餅
    public class Jialiaojianbing extends Jianbing{
        protected Jianbing jianbing;
        public void SetComponent(Jianbing jianbing){
            this.jianbing = jianbing;
        }

        @Override
        public void Operation()
        {
            if(jianbing !=null){
                jianbing.Operation();  
            }
        }
        
    }
    //加香腸的煎餅
    public class Xiangchang extends Jialiaojianbing{
        private void AddedBehavior(){
            System.out.println("加香腸");
        }
        @Override
        public void Operation()
        {
            super.Operation();
            AddedBehavior();
        }
        
    }
    //加辣條煎餅
    public class Latiao extends Jialiaojianbing{
        private void AddedBehavior(){
            System.out.println("加辣條");
        }
        @Override
        public void Operation()
        {
            super.Operation();
            AddedBehavior();
        }
    }
    public void main(String[] args){
        Yuanweijianbing j = new Yuanweijianbing();
        Xiangchang d1 = new Xiangchang();
        Latiao d2 = new Latiao();
        d1.SetComponent(j);
        d2.SetComponent(d1);
        d2.Operation();
    }

    這樣無論你想吃什麼樣的煎餅,裝飾器模式都能幫你做到,先後順序由你來定。老闆,來一份加腸加辣條的煎餅。九塊不謝!

    裝飾模式是為已有功能動態地新增更多功能的一種方式。當系統需要新功能的時候,比如在主類中假如新的欄位,新的方法和新的邏輯,從而增加主類的複雜度,而這些新加入的東西僅僅是為了滿足一些只在某種特定情況下才會執行的特殊行為的需要,裝飾模式提供了一個非常好的解決方案,它把每個要裝飾的功能放在單獨的類中,並讓這個類包裝它索要裝飾的物件,因此,當需要執行特殊行為時,客戶程式碼就可以在執行時根據需要有選擇的、按順序地使用裝飾功能包裝物件了。這樣做的好處就是有效地把類的核心職責和裝飾功能區分開。而且可以去除相關類中重複的裝飾邏輯。其實裝飾類就是在原有類基礎上的加強或者說是多穿了一層。java IO 流中裝飾設計模式是非常常見的,大家可以自行去檢視原始碼體會。