1. 程式人生 > >設計模式之裝飾(Decorator)模式

設計模式之裝飾(Decorator)模式

isp 撤銷 有一個 inf 替代 接受 需要 裝飾著模式 ()

設計模式之裝飾(Decorator)模式

(一)什麽是裝飾(Decorator)模式

  裝飾模式,又稱為包裝模式,它以對客戶端透明的方式擴張對象的功能,是繼承關系的替代方案之一。
  裝飾模式可以在不使用創造更多子類的情況下,將對象的功能加以擴展。

(二)裝飾模式的角色

  1)抽象構件(Component)角色:給出一個抽象接口,以規範準備接受附加責任的對象
  2)具體構件(Concrete component)角色:定義一個將要接受附加責任的類
  3)裝飾角色(Decorator)角色:持有一個構建(Component)對象的實例
  4)具體裝飾(Concrete decorator)角色:負責給構件對象添加功能。

技術分享圖片

(三)裝飾模式的實現

  想象一下這樣一種情況,定義了一個接口Car(代碼如下),裏邊只包含一個方法move(),這個方法用來展示具體車的移動方式。

public interface Car {
    void move();
}

  首先我們創建一個最普通的車RunCar(這裏的普通指的是移動方式為陸地移動),實現這個接口。

public class RunCar implements Car {

    @Override
    public void move() {
        this.run();
    }
    
    public void run() {
        System.out.println("可以跑");
    }
    
}

  隨著科技的進步,可能會有能夠飛的車FlyCar,可能會有SwimCar,我們首先想到的實現方式就是繼承,通過子類的實現擴展父類的功能,在這裏指的是分別創建FlyCar類和SwimCar類實現Car接口。如果有這樣一種需求,創建一種既能飛fly也能swim的FlySwimCar,這樣該如何實現的,傳統的繼承能夠實現,但一方面java只支持單繼承,靈活性較差,另一方面,之前已經分別創建了FlyCar和SwimCar,如果再創建FlySwimCar會造成代碼重復,想象一下,如果能夠在FlyCar的基礎上擴展swim功能就好了。

  恰巧,裝飾著模式就能解決此類問題。

  這裏我們的Component角色 指的就是Car接口,它既是被裝飾類的父接口,也是裝飾類的父接口。

  RunCar扮演的就是被裝飾者的角色,它是Component角色的實現類。

  抽象裝飾角色為CarDecorator,實現了Car接口,切內部包含一個Car的引用,用來保存被裝飾的對象:

public abstract class CarDecorator implements Car  {
    private Car car;
    public CarDecorator(Car car) {
        this.car = car;
    }
    
    
    public Car getCar() {
        return car;
    }


    public void setCar(Car car) {
        this.car = car;
    }


    public abstract void move();
} 

  具體抽象角色用於具體功能的擴展,在這裏SwimCarDecorator為傳進的汽車對象增加swim功能,FlyCarDecorator為傳進的汽車對象增加fly功能。

public class SwimCarDecorator extends CarDecorator {

    public SwimCarDecorator(Car car) {
        super(car);
    }
    
    public void move() {
        this.getCar().move();
        this.swim();
    }
    
    public void swim() {
        System.out.println("可以遊");
    }

}
public class FlyCarDecorator extends CarDecorator {

    public FlyCarDecorator(Car car) {
        super(car);
    }

    @Override
    public void move() {
        this.getCar().move();
        this.fly();
    }
    
    public void fly() {
        System.out.println("可以飛");
    }
    
}

  這樣以來,如果要創建一個會飛的汽車,那麽把一個普通汽車傳給FlyCarDecorator即可,如果創建一個會swim的車,把普通汽車傳給SwimDecorator即可,如果想創建一個既會fly也會swim,只需把一個普通對的車傳給FlyCarDecorator,再傳給SwimDecorator即可。

public class Client {
    public static void main(String[] args) {
        Car runCar = new RunCar();
        runCar.move();
        System.out.println("-----------");
        Car flyCar = new FlyCarDecorator(runCar);
        flyCar.move();
        System.out.println("-----------");
        Car flySwimCar = new SwimCarDecorator(new FlyCarDecorator(new RunCar()));
        flySwimCar.move();
    }
}

(四)在什麽情況下使用裝飾模式

  需要擴展一個類的功能,或給一個類增加附加責任。
  需要動態地給一個對象增加功能,這些功能可以動態的撤銷
  需要增加由一些基本功能排列則和而產生的非常大量的功能,從而使繼承關系變得不顯示。

(五)裝飾模式的簡化

  1)如果只有一個ConcreteComponent類而沒有抽象的Component接口,可以把Decorator類設為ConcreteComponent的一個子類  
  2)如果只有一個ConcreteDecorator類,就沒有必要定義Decorator類

(六)裝飾模式的優缺點  

  優點:
    1)裝飾模式與繼承關系的目的都是擴展對象的功能,裝飾模式可以提供比繼承更多的靈活性。繼承是靜態的,而裝飾是動態的。
    2)通過使用不同的具體裝飾類以及這些裝飾類的排列組合,設計師可是設計出很多不同行為的組合。
  缺點:
   使用裝飾比使用繼承需要更少數目的類,使用較少的類當然設計比較易於進行,但另一方面,裝飾模式會產生比繼承關系更多的對象,這些對象看上去都很相似,因此查錯更為困難。

設計模式之裝飾(Decorator)模式