設計模式——裝飾器模式

設計模式——裝飾器模式

1-裝飾器模式的定義

裝飾器模式定義:動態的爲一個對象增加新的功能,用於代替繼承的技術,無須通過繼承增加子類就能擴展對象的新功能。使用對象的關聯關係代替繼承關係,更加靈活,同時避免類型體系的快速膨脹。當需要給一個已有的類的功能上新增功能時,裝飾器模式提供了一個很好的解決方案,它把每個要裝飾的功能放在單獨的類中,並讓這個類包裝它需要裝飾的對象,因此,當需要執行特殊行爲時,客戶代碼就可以在運行時根據需要有選擇地、按順序地使用裝飾功能包裝對象。

No BB,Show Code!

 

2-裝飾器模式的具體代碼實現

2-1定義一個接口

定義一個接口,該接口定義一個可以不斷擴展功能的方法!

package designPattern.test.decorator;

/**
 * 行駛接口,有一個move()方法,可以通過裝飾器不斷增強功能
 */
public interface Driving {
    void move();
}

2-2定義兩個簡單實現

簡單實現1-Bike

package designPattern.test.decorator;

/**
 * 自行車行駛
 */
public class Bike implements Driving {

    /**
     * 初始的自行車行駛方法
     */
    @Override
    public void move() {
       System.out.println("鏈條傳動自行車,騎着累啊!");
    }

}

簡單實現2-Car

package designPattern.test.decorator;

/**
 * 汽車
 */
public class Car implements Driving {

    @Override
    public void move() {
        System.out.println("汽車行駛,速度快!");
    }

}

2-3定義一個抽象裝飾類

package designPattern.test.decorator;

/**
 * 抽象的裝飾類
 */
public abstract class DrivingDecorator implements Driving {

    private Driving driving;

    public DrivingDecorator() {
    }

    /**
     * 被裝飾的對象作爲構造器參數傳入
     */
    public DrivingDecorator(Driving driving) {
        this.driving = driving;
    }

    public Driving getDriving() {
        return driving;
    }

    public void setDriving(Driving driving) {
        this.driving = driving;
    }

    /**
     * 實現基礎的功能
     */
    @Override
    public void move() {
        driving.move();
    }

}

2-4定義具體的裝飾類

具體裝飾類1-FlyDecorator

package designPattern.test.decorator;

/**
 * 飛行裝飾類
 */
public class FlyDecorator extends DrivingDecorator {

    /**
     * 被裝飾的對象唄裝飾對象所持有
     */
    public FlyDecorator(Driving driving) {
        super(driving);
    }

    /**
     * 裝飾對象新增方法
     */
    public void fly() {
        System.out.println("飛起來了");
    }

    /**
     * 功能增強的move方法
     */
    public void move() {
        super.move();
        fly();
    }

}

定義具體的裝飾類-WaterDecorator

package designPattern.test.decorator;

/**
 * 入海行駛裝飾器
 */
public class WaterDecorator extends DrivingDecorator {

    /**
     * 被裝飾的對象唄裝飾對象所持有
     */
    public WaterDecorator(Driving driving) {
        super(driving);
    }

    /**
     * 裝飾對象新增方法
     */
    public void water() {
        System.out.println("遊起來了");
    }

    /**
     * 功能增強的move方法
     */
    public void move() {
        super.move();
        water();
    }

}

定義具體的實現類-AIDecorator

package designPattern.test.decorator;

/**
 * 智能裝飾
 */
public class AIDecorator extends DrivingDecorator {

    /**
     * 被裝飾的對象唄裝飾對象所持有
     */
    public AIDecorator(Driving driving) {
        super(driving);
    }

    /**
     * 裝飾對象新增方法
     */
    public void ai() {
        System.out.println("智能起來了");
    }

    /**
     * 功能增強的move方法
     */
    public void move() {
        super.move();
        ai();
    }

}

如代碼所示,每一個具體的裝飾類都繼承了抽象的裝飾類,將被裝飾的對象作爲裝飾對象的構造器參數傳入,不斷的增強被裝飾對象的功能!不同的裝飾功能可以放在不同的類中,每個裝飾器類只需考慮自己需要增強的功能,這樣代碼看起來將更加清晰!

3-測試

測試代碼如下

package designPattern.test.decorator;

import org.junit.Test;

/**
 * 裝飾器模式測試
 */
public class DecoratorTest {

    @Test
    public void testDecorator(){
        Driving bike = new FlyDecorator(new Bike());
        bike.move();
        Driving bike1 = new WaterDecorator(new Bike());
        bike1.move();
        Driving bike2 = new AIDecorator(new Bike());
        bike2.move();
        Driving car = new AIDecorator(new Car());
        car.move();
    }

}

打印結果如下:

鏈條傳動自行車,騎着累啊!
飛起來了
鏈條傳動自行車,騎着累啊!
遊起來了
鏈條傳動自行車,騎着累啊!
智能起來了
汽車行駛,速度快!
智能起來了

總結:裝飾器模式可以在原有類的基礎功能保持不變的情況下,增加新的功能,而且可以不斷的增加新的功能,這些新增功能的使用也完全由程序員控制,每個裝飾器類單獨分開,各自新增不同的功能,代碼層次清晰易懂!

4-裝飾器模式的典型應用

裝飾器模式最典型的應用可以說是jdk中的IO系統,代碼如下:

package designPattern.test.decorator.fileDecorator;

import org.junit.Test;

import java.io.*;

/**
 * io系統的裝飾器應用
 */
public class FileTest {

    @Test
    public void testFileInputStream() throws Exception{
        long start = System.currentTimeMillis();
        InputStream inputStream = new FileInputStream(new File("D:/trace.log"));
        printLog(inputStream);
        System.out.println("============================Time:"+(System.currentTimeMillis() - start));
    }

    @Test
    public void testFileBuffered() throws Exception {
        long start = System.currentTimeMillis();
        InputStream inputStream = new BufferedInputStream(new FileInputStream(new File("D:/trace.log")));
        printLog(inputStream);
        System.out.println("============================Time:"+(System.currentTimeMillis() - start));
    }

    @Test
    public void testFileDataInputStream() throws Exception {
        long start = System.currentTimeMillis();
        InputStream inputStream = new DataInputStream(new BufferedInputStream(new FileInputStream(new File("D:/trace.log"))));
        printLog(inputStream);
        System.out.println("============================Time:"+(System.currentTimeMillis() - start));
    }

    private void printLog(InputStream inputStream) throws Exception{
        int i = 0;
        byte[] b = new byte[1024];
        while ((i = inputStream.read(b)) != -1) {
            String s = new String(b);
            System.out.println(s);
        }
    }

}

代碼中,FileInputStream,BufferedInputStream,DataInputStream都是InputStream抽象類的具體實例,FileInputStream的實例可以作爲傳參傳入BufferedInputStream中,給文件IO新增緩衝區作用,類似於批量處理,提高了IO性能,同樣可以把BufferedInputStream的實例作爲傳參傳給DataInputStream的構造器中,給文件IO新增數據格式輸入的功能(存疑)!


發佈了31 篇原創文章 · 獲贊 41 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章