設計模式,結構模式之裝飾模式

1 概述

裝飾模式(Decorator Pattern),意在不改變原有對象的情況下,改變/增強它的方法。

2 裝飾模式

在不違反開閉原則的前提下,要改變某個對象的行爲,可以使用繼承。然而繼承不適用於類/方法被final修飾的情況,而且一般需要了解類內部的情況,違反了迪米特法則
裝飾模式體現了組合優先於繼承的思想,通過組合的方式,“裝飾”對象的功能,也能達到改變對象行爲的目的。裝飾模式的實現模式和代理模式很相似,都是實現目標對象的接口,然後持有目標類,調用目標類的方法。代理模式更偏向於對對象的控制,給對象添加與其無關的功能(打日誌,權限校驗等);而裝飾模式更偏向於對對象的增強,即增強對象原有的方法,裝飾後的對象還是原來的對象。

3 案例

舉個例子。定義一個Car接口,看如何用裝飾模式在不修改原有對象的基礎上,對其方法進行增強:

public class Test {
    public static void main(String[] args) {
        Car basicCar = new BasicCar();
        // 裝飾類
        Car sportsCar = new SportsCar(basicCar);
        basicCar.drive();
        System.out.println("top speed of basic car: " + basicCar.topSpeed());
        System.out.println("=============");
        sportsCar.drive();
        System.out.println("top speed of sports car: " + sportsCar.topSpeed());
    }
}

public interface Car {
    void drive();
    int topSpeed();
}

public class BasicCar implements Car {
    @Override
    public void drive() {
        System.out.println("Car is driving...");
    }
    @Override
    public int topSpeed() {
        return 120;
    }
}

// 裝飾類
public class SportsCar implements Car {
    // 被裝飾對象
    Car car;
    SportsCar(Car car) {
        this.car = car;
    }
    // 對drive()方法進行增強
    @Override
    public void drive() {
        System.out.println("Sports Car is build with high performance engine...");
        car.drive();
    }
    // 對topSpeed()方法進行增強
    @Override
    public int topSpeed() {
        return car.topSpeed() + 60;
    }
}

輸出:

Car is driving...
top speed of basic car: 120
=============
Sports Car is build with high performance engine...
Car is driving...
top speed of sports car: 180

裝飾類SportsCar實現了被裝飾對象的接口,同時持有被裝飾對象的實例,在調用被裝飾對象的方法前後進行“裝飾”。不影響原有類BasicCar的邏輯,符合開閉原則

JavaCollections工具類就使用了裝飾模式synchronizedCollection(Collection<T> c)方法返回了一個裝飾對象,對集合添加了同步處理,unmodifiableCollection(Collection<? extends T> c)方法返回了一個裝飾對象,使得集合不能被修改。

4 總結

使用裝飾模式可以在不改變原對象邏輯的情況下,實現對象方法的增強。

文中例子的github地址

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