Java設計模式之--橋接模式(bridge pattern)

概念:
橋接模式的用意是"將抽象化(Abstraction)與實現化(Implementation)脫耦,使得二者可以獨立地變化"。實際項目中遇到某些類由於自身的邏輯,它具有兩個或多個維度的變化,那麼如何應對這種“多維度的變化”?如何利用面嚮對象的技術來使得該類型能夠輕鬆的沿着多個方向進行變化,而又不引入額外的複雜度?這就要使用Bridge模式。。像我們常用的JDBC橋DriverManager一樣,JDBC進行連接數據庫的時候,在各個數據庫之間進行切換,不需要動太多的代碼,甚至絲毫不用動,原因就是JDBC提供統一接口,每個數據庫提供各自的實現,用一個叫做數據庫驅動的程序來橋接就行了。我們來看看關係圖:

代碼:
Driver interface
public interface Driver {
    public boolean connect(String uri);
    public Cursor query(String query);
}
bridge class:
public abstract class DriverBridge {
    private Driver driver;

    public Driver getDriver() {
        return driver;
    }

    public void setDriver(Driver driver) {
        this.driver = driver;
    }

    public abstract boolean connect(String uri);

    public abstract Cursor query(String query);
}

有了橋再有兩邊:
db 實現類:
public class MysqlDriver implements Driver {
    @Override
    public boolean connect(String uri) {
        System.out.println(String.format("%s.%s called!", this.getClass().getName(), "connect()"));
        return false;
    }

    @Override
    public Cursor query(String query) {
        System.out.println(String.format("%s.%s called!", this.getClass().getName(), "query()"));
        return null;
    }
}
public class DB2Driver implements Driver {
    @Override
    public boolean connect(String uri) {
        System.out.println(String.format("%s.%s called!", this.getClass().getName(), "connect()"));
        return false;
    }

    @Override
    public Cursor query(String query) {
        System.out.println(String.format("%s.%s called!", this.getClass().getName(), "query()"));
        return null;
    }
}

public class OracleDriver implements Driver {

    @Override
    public boolean connect(String uri) {
        System.out.println(String.format("%s.%s called!", this.getClass().getName(), "connect()"));
        return false;
    }

    @Override
    public Cursor query(String query) {
        System.out.println(String.format("%s.%s called!", this.getClass().getName(), "query()"));
        return null;
    }
}

user bridge class:
public class WeatherBridge extends DriverBridge {
    @Override
    public boolean connect(String uri) {
        return getDriver().connect(uri);
    }

    @Override
    public Cursor query(String query) {
        return getDriver().query(query);
    }
}

測試類:
public class WorkClass {
    public void test() {
        DriverBridge driverBridge = new WeatherBridge();
        driverBridge.setDriver(new MysqlDriver());
        driverBridge.connect("");
        driverBridge.query("");
        driverBridge.setDriver(new DB2Driver());
        driverBridge.connect("");
        driverBridge.query("");
    }
}

測試結果 :
I/System.out: com.example.qinghua_liu.myapplication.designpatten.struct.adapt.MysqlDriver.connect() called!
I/System.out: com.example.qinghua_liu.myapplication.designpatten.struct.adapt.MysqlDriver.query() called!
I/System.out: com.example.qinghua_liu.myapplication.designpatten.struct.adapt.DB2Driver.connect() called!
I/System.out: com.example.qinghua_liu.myapplication.designpatten.struct.adapt.DB2Driver.query() called!

案例二:
天氣類應用,天氣狀態分晴天和雨天,現有功能需要擴展,增加夜晚狀態,這樣天氣狀態存在變化,時間白天夜晚又存在另一維度的變化,應用橋接模式如下:
先寫天氣接口:
public interface Weather {
    public String getWeatherText();
}
兩個接口的實現類:
public class Sunny implements Weather {

    @Override
    public String getWeatherText() {
        return "clear";
    }
}

public class Rain implements Weather {

    @Override
    public String getWeatherText() {
        return "rainy";
    }
}
天氣橋接抽象類:
public abstract class WeatherBridge {

    private Weather weather;

    public WeatherBridge(Weather weather) {
        this.weather = weather;
    }

    public Weather getWeather() {
        return weather;
    }

    public void setWeather(Weather weather) {
        this.weather = weather;
    }


    public abstract String showWeather();
}

抽象的子類白天類與夜晚類:
public class DayTimeWeather extends WeatherBridge {
    @Override
    public String showWeather() {
        //System.out.println(String.format("A %s day time", getWeather().getWeatherText()));
        return String.format("A %s day time", getWeather().getWeatherText());
    }

    public DayTimeWeather(Weather weather) {
        super(weather);
    }
}

public class NightWeather extends WeatherBridge {
    @Override
    public String showWeather() {
//        System.out.println(String.format("A %s night", getWeather().getWeatherText()));
        return String.format("A %s night", getWeather().getWeatherText());
    }

    public NightWeather(Weather weather) {
        super(weather);
    }
}
測試:
WeatherBridge weatherBridge= new DayTimeWeather(new Sunny());
System.out.println(weatherBridge.showWeather());
weatherBridge.setWeather(new Rain());
System.out.println(weatherBridge.showWeather());

weatherBridge = new NightWeather(new Sunny());
System.out.println(weatherBridge.showWeather());

weatherBridge.setWeather(new Rain());
System.out.println(weatherBridge.showWeather());

輸出:
 I/System.out: A clear day time
 I/System.out: A rainy day time
I/System.out: A clear night
I/System.out: A rainy night

再加擴展:區分季節狀態,再加第三維狀態:
定義季節天氣橋抽象類:
public abstract class SeasonBridge {
    private WeatherBridge weatherBridge;

    public SeasonBridge(WeatherBridge weatherBridge) {
        this.weatherBridge = weatherBridge;
    }

    public WeatherBridge getWeatherBridge() {
        return weatherBridge;
    }

    public void setWeatherBridge(WeatherBridge weatherBridge) {
        this.weatherBridge = weatherBridge;
    }

    public abstract String showWeather();

}

定義上面抽象類的實現類:夏季,冬季
public class Summer extends SeasonBridge {
    public Summer(WeatherBridge weatherBridge) {
        super(weatherBridge);
    }

    @Override
    public String showWeather() {
        return String.format("%s in summer",getWeatherBridge().showWeather());

    }
}

public class Winter extends SeasonBridge {
    public Winter(WeatherBridge weatherBridge) {
        super(weatherBridge);
    }

    @Override
    public String showWeather() {
        return String.format("%s in winter",getWeatherBridge().showWeather());

    }
}

測試代碼:

        
WeatherBridge weatherBridge= new DayTimeWeather(new Sunny());
SeasonBridge seasonBridge = new Summer(weatherBridge);
System.out.println(seasonBridge.showWeather());
weatherBridge.setWeather(new Rain());
System.out.println(seasonBridge.showWeather());
seasonBridge.setWeatherBridge(new NightWeather(new Sunny()));
System.out.println(seasonBridge.showWeather());
seasonBridge = new Winter(weatherBridge);
System.out.println(seasonBridge.showWeather());

輸出結果:
I/System.out: A clear day time in summer
I/System.out: A rainy day time in summer
I/System.out: A clear night in summer
I/System.out: A rainy day time in winter


橋樑模式和適配器模式的區別
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章