国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

一起學(xué)設(shè)計(jì)模式 - 橋接模式

tinysun1234 / 1208人閱讀

摘要:橋接模式屬于結(jié)構(gòu)型模式的一種,用于把抽象化與實(shí)現(xiàn)化解耦,使得二者可以獨(dú)立變化,它通過(guò)提供抽象化和實(shí)現(xiàn)化之間的橋接結(jié)構(gòu),來(lái)實(shí)現(xiàn)二者的解耦。相關(guān)模式裝飾模式與橋接模式在一定程度上都是為了減少子類(lèi)的數(shù)目,避免出現(xiàn)復(fù)雜的繼承關(guān)系。

橋接模式(Brideg Pattern)屬于結(jié)構(gòu)型模式的一種,用于把抽象化與實(shí)現(xiàn)化解耦,使得二者可以獨(dú)立變化,它通過(guò)提供抽象化和實(shí)現(xiàn)化之間的橋接結(jié)構(gòu),來(lái)實(shí)現(xiàn)二者的解耦。

概述

橋接模式是一種很實(shí)用的結(jié)構(gòu)型設(shè)計(jì)模式,如果軟件系統(tǒng)中某個(gè)類(lèi)存在兩個(gè)獨(dú)立變化的維度,通過(guò)該模式可以將這兩個(gè)維度分離出來(lái),使兩者可以獨(dú)立擴(kuò)展,讓系統(tǒng)更加符合“單一職責(zé)原則”。與多層繼承方案不同,它將兩個(gè)獨(dú)立變化的維度設(shè)計(jì)為兩個(gè)獨(dú)立的繼承等級(jí)結(jié)構(gòu),并且在抽象層建立一個(gè)抽象關(guān)聯(lián),該關(guān)聯(lián)關(guān)系類(lèi)似一條連接兩個(gè)獨(dú)立繼承結(jié)構(gòu)的橋,故名橋接模式。

橋接模式用一種巧妙的方式處理多層繼承存在的問(wèn)題,用抽象關(guān)聯(lián)取代了傳統(tǒng)的多層繼承,將類(lèi)之間的靜態(tài)繼承關(guān)系轉(zhuǎn)換為動(dòng)態(tài)的對(duì)象組合關(guān)系,使得系統(tǒng)更加靈活,并易于擴(kuò)展。

合成復(fù)用原則

合成復(fù)用原則又稱為組合/聚合復(fù)用原則(Composition/Aggregate Reuse Principle, CARP),指盡量使用對(duì)象組合,而不是繼承來(lái)達(dá)到復(fù)用的目的。

為什么要盡量使用合成和聚合,而不用繼承

繼承復(fù)用破壞包裝,它把父類(lèi)的實(shí)現(xiàn)細(xì)節(jié)直接暴露給了子類(lèi),父類(lèi)發(fā)生改變,則子類(lèi)也要發(fā)生相應(yīng)的改變,這就直接導(dǎo)致了類(lèi)之間的緊耦合,不利于類(lèi)的擴(kuò)展、復(fù)用、維護(hù)。

合成與聚合的時(shí)候,對(duì)象交互往往是通過(guò)接口或抽象類(lèi)進(jìn)行的,可以很好的避免上面的不足,每個(gè)新的類(lèi)專注于實(shí)現(xiàn)自己的任務(wù),符合單一職責(zé)原則。

案例

拿汽車(chē)在路上行駛的來(lái)說(shuō)。即有小汽車(chē)又有公共汽車(chē),它們都不但能在市區(qū)中的公路上行駛,也能在高速公路上行駛。這你會(huì)發(fā)現(xiàn),對(duì)于交通工具(汽車(chē))有不同的類(lèi)型,然而它們所行駛的環(huán)境(路)也在變化,在軟件系統(tǒng)中就要適應(yīng)兩個(gè)方面的變化?怎樣實(shí)現(xiàn)才能應(yīng)對(duì)這種變化呢?

緊耦合示例

1.定義基類(lèi)Road,它擁有在上面行駛的方法

class Road {
    public void run() {
        System.out.println("在路上");
    }
}

2.路也有多種,這時(shí)候咋整?繼承一波唄

class SpeedWay extends Road {
    @Override
    public void run() {
        System.out.println("在高速公路上");
    }
}

class Street extends Road {
    @Override
    public void run() {
        System.out.println("在市區(qū)街道上");
    }
}

3.問(wèn)題來(lái)了,不同的路跑著不同的車(chē),這個(gè)時(shí)候針對(duì)不同的車(chē)都要繼承SpeedWay/Street兩個(gè)類(lèi),假設(shè)我有(5種車(chē) 5條不同的路),媽呀那得多少類(lèi),先 (2 2)吧

class CarOnSpeedWay extends SpeedWay {
    @Override
    public void run() {
        System.out.println("汽車(chē)在高速公路上行駛");
    }
}

class BusOnSpeedWay extends SpeedWay {
    @Override
    public void run() {
        System.out.println("公共汽車(chē)在高速公路上行駛");
    }
}


class CarOnStreet extends Street {
    @Override
    public void run() {
        System.out.println("汽車(chē)在街道上行駛");
    }
}

class BusOnStreet extends Street {
    @Override
    public void run() {
        System.out.println("公共汽車(chē)在街道上行駛");
    }
}

4.編寫(xiě)測(cè)試類(lèi),有木有發(fā)現(xiàn)代碼啰嗦不說(shuō),不是說(shuō)好的一般是面向接口編程么?

public class Client {

    public static void main(String[] args) {
        CarOnSpeedWay carOnSpeedWay = new CarOnSpeedWay();
        carOnSpeedWay.run();

        BusOnSpeedWay busOnSpeedWay = new BusOnSpeedWay();
        busOnSpeedWay.run();

        CarOnStreet carOnStreet = new CarOnStreet();
        carOnStreet.run();

        BusOnStreet busOnStreet = new BusOnStreet();
        busOnStreet.run();
    }
}

弊端: 仔細(xì)分析就可以發(fā)現(xiàn),該方案雖然實(shí)現(xiàn)了功能但埋了不少坑,它在遵循開(kāi)放-封閉原則的同時(shí),違背了類(lèi)的單一職責(zé)原則,即一個(gè)類(lèi)只有一個(gè)引起它變化的原因,而這里引起變化的原因卻有兩個(gè),即路類(lèi)型的變化和汽車(chē)類(lèi)型的變化;其次是重復(fù)代碼會(huì)很多,不同的汽車(chē)在不同的路上行駛也會(huì)有一部分的代碼是相同的;再次是類(lèi)的結(jié)構(gòu)過(guò)于復(fù)雜,繼承關(guān)系太多,難于維護(hù),最后最致命的一點(diǎn)是擴(kuò)展性太差。如果變化沿著汽車(chē)的類(lèi)型和不同的道路兩個(gè)方向變化,我們會(huì)看到這個(gè)類(lèi)的結(jié)構(gòu)會(huì)迅速的變龐大。

松耦合示例

首先我們要搞清楚,路上面可以行駛車(chē)輛(包含),但車(chē)并不是路的一部分,它們二者并不一定要緊密貼在一塊,它們之間是聚合關(guān)系

1.定義一個(gè)Car的接口,供給不同種類(lèi)的去實(shí)現(xiàn)

interface Car {
    void run();
}

2.抽象類(lèi)AbstractRoad,與Car關(guān)聯(lián)起來(lái),接收具體的實(shí)現(xiàn)

abstract class AbstractRoad {
    protected Car car;

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

3.道路類(lèi)統(tǒng)一繼承AbstractRoad實(shí)現(xiàn)抽象方法,汽車(chē)類(lèi)統(tǒng)一實(shí)現(xiàn)Car接口

class SpeedWay extends AbstractRoad {
    @Override
    public void run() {
        car.run();
        System.out.println("在高速公路上");
    }
}

class Street extends AbstractRoad {
    @Override
    public void run() {
        car.run();
        System.out.println("在市區(qū)街道上");
    }
}

class SmallCar implements Car {
    @Override
    public void run() {
        System.out.println("小汽車(chē)");
    }
}
class BigTruck implements Car {
    @Override
    public void run() {
        System.out.println("大卡車(chē)");
    }
}

4.編寫(xiě)測(cè)試類(lèi),通過(guò)傳入具體實(shí)現(xiàn)來(lái)獲得最終結(jié)果

public class Client {

    public static void main(String[] args) {
        Car bigTruck = new BigTruck();
        Car smallCar = new SmallCar();
        AbstractRoad way = new SpeedWay();
        way.setCar(bigTruck);
        way.run();
        way.setCar(smallCar);
        way.run();

        AbstractRoad street = new Street();
        street.setCar(bigTruck);
        street.run();
        street.setCar(smallCar);
        street.run();
    }
}

可以看到,通過(guò)對(duì)象組合的方式,Bridge 模式把兩個(gè)角色之間的繼承關(guān)系改為了聚合的關(guān)系,從而使這兩者可以從容自若的各自獨(dú)立的變化,這也是Bridge模式的本意。

多維度變化

結(jié)合上面的例子,增加一個(gè)維度"人",不同的人開(kāi)著不同的汽車(chē)在不同的路上行駛(三個(gè)維度);結(jié)合上面增加一個(gè)類(lèi)"人",并重新調(diào)用.

abstract class People {

    protected AbstractRoad abstractRoad;

    public void setAbstractRoad(AbstractRoad abstractRoad) {
        this.abstractRoad = abstractRoad;
    }

    public abstract void run();
}

class Man extends People {

    @Override
    public void run() {
        System.out.println("男人開(kāi)著");
        abstractRoad.run();
    }
}

public class Client {

    public static void main(String[] args) {
        Car bigTruck = new BigTruck();
        People people = new Man();
        AbstractRoad street = new Street();
        street.setCar(bigTruck);
        people.setAbstractRoad(street);
        people.run();
    }
}
JDBC與橋接

通常使用JDBC連接數(shù)據(jù)庫(kù)時(shí),首選就是加載數(shù)據(jù)庫(kù)驅(qū)動(dòng),然后獲取數(shù)據(jù)庫(kù)連接

Class.forName("數(shù)據(jù)庫(kù)類(lèi)驅(qū)動(dòng)器");
Connection conn = DriverManager.getConnection("數(shù)據(jù)庫(kù)url", "用戶名", "密碼");
//.................

針對(duì)不同的數(shù)據(jù)庫(kù),JDBC都可以通過(guò)java.sql.DriverManager類(lèi)的靜態(tài)方法getConnection(數(shù)據(jù)庫(kù)url, 用戶名, 密碼)來(lái)獲取數(shù)據(jù)庫(kù)的連接。JDBC通過(guò)DriverManager對(duì)外提供了操作數(shù)據(jù)庫(kù)的統(tǒng)一接口getConnection,通過(guò)該方法可以獲取不同數(shù)據(jù)庫(kù)的連接,并且通過(guò)Connection類(lèi)提供的接口來(lái)進(jìn)行數(shù)據(jù)的查詢操作。

JDBC為不同的數(shù)據(jù)庫(kù)操作提供了相同的接口,但是JDBC本身并沒(méi)有針對(duì)每種數(shù)據(jù)庫(kù)提供一套具體實(shí)現(xiàn)代碼,而是通過(guò)接口java.sql.Driver的connect方法連接到了不同的數(shù)據(jù)庫(kù)實(shí)現(xiàn)。

public interface Driver {

    Connection connect(String url, java.util.Properties info) throws SQLException;
    //其他方法
}

在JDBC中,針對(duì)不同數(shù)據(jù)庫(kù)提供的統(tǒng)一的操作接口通過(guò)java.sql.Driver(橋)連接到了不同的數(shù)據(jù)庫(kù)實(shí)現(xiàn)。如連接mysql數(shù)據(jù)庫(kù)。

package com.mysql.jdbc;

public class NonRegisteringDriver implements java.sql.Driver { 

    public java.sql.Connection connect(String url, Properties info) throws SQLException {
        //省略具體實(shí)現(xiàn)代碼...
    }

    //其他方法
}
具體實(shí)現(xiàn)

1.在com.mysql.jdbc.Driver的源碼中可以看到,類(lèi)加載時(shí)會(huì)將Driver注冊(cè)到DriverManager中。

package com.mysql.jdbc;

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    static {
        try {
            java.sql.DriverManager.registerDriver(new Driver());
        } catch (SQLException E) {
            throw new RuntimeException("Can"t register driver!");
        }
    }

    public Driver() throws SQLException {
        // Required for Class.forName().newInstance()
    }
}

2.在DriverManager中,調(diào)用getConnection會(huì)迭代驅(qū)動(dòng)注冊(cè)表中的驅(qū)動(dòng),然后調(diào)用Driver接口提供的connect方法來(lái)獲取Connection對(duì)象

public class DriverManager {
    
    // JDBC驅(qū)動(dòng)程序注冊(cè)表
    private final static CopyOnWriteArrayList registeredDrivers = new CopyOnWriteArrayList<>();
    
    
    public static synchronized void registerDriver(java.sql.Driver driver,
            DriverAction da)
        throws SQLException {
    
        /* Register the driver if it has not already been added to our list */
        if(driver != null) {
            registeredDrivers.addIfAbsent(new DriverInfo(driver, da));
        } else {
            // This is for compatibility with the original DriverManager
            throw new NullPointerException();
        }
    
        println("registerDriver: " + driver);
    
    }
    
    private static Connection getConnection(String url, java.util.Properties info, Class caller) throws SQLException {
            ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
            synchronized(DriverManager.class) {
                // synchronize loading of the correct classloader.
                if (callerCL == null) {
                    callerCL = Thread.currentThread().getContextClassLoader();
                }
            }
    
            if(url == null) {
                throw new SQLException("The url cannot be null", "08001");
            }
    
            println("DriverManager.getConnection("" + url + "")");

            SQLException reason = null;
            //遍歷registeredDrivers表
            for(DriverInfo aDriver : registeredDrivers) {
                // 如果沒(méi)有加載驅(qū)動(dòng)的權(quán)限則跳過(guò)
                if(isDriverAllowed(aDriver.driver, callerCL)) {
                    try {
                        //調(diào)用Driver接口提供的connect方法來(lái)獲取Connection對(duì)象
                        println("    trying " + aDriver.driver.getClass().getName());
                        Connection con = aDriver.driver.connect(url, info);
                        if (con != null) {
                            // Success!
                            println("getConnection returning " + aDriver.driver.getClass().getName());
                            return (con);
                        }
                    } catch (SQLException ex) {
                        if (reason == null) {
                            reason = ex;
                        }
                    }
    
                } else {
                    println("    skipping: " + aDriver.getClass().getName());
                }
    
            }
    
            // if we got here nobody could connect.
            if (reason != null)    {
                println("getConnection failed: " + reason);
                throw reason;
            }
            println("getConnection: no suitable driver found for "+ url);
            throw new SQLException("No suitable driver found for "+ url, "08001");
        }
    }
}

上述代碼中為橋接模式在JDBC中運(yùn)用方式

總結(jié)

實(shí)現(xiàn)要點(diǎn)

Bridge模式使用對(duì)象間的組合關(guān)系解耦了抽象和實(shí)現(xiàn)之間固有的綁定關(guān)系,使得抽象和實(shí)現(xiàn)可以沿著各自的維度來(lái)變化。

所謂抽象和實(shí)現(xiàn)沿著各自維度的變化,即子類(lèi)化它們,得到各個(gè)子類(lèi)之后,便可以任意它們,從而獲得不同路上的不同汽車(chē)。

Bridge模式有時(shí)候類(lèi)似于多繼承方案,但是多繼承方案往往違背了類(lèi)的單一職責(zé)原則(即一個(gè)類(lèi)只有一個(gè)變化的原因),復(fù)用性比較差。Bridge模式是比多繼承方案更好的解決方法。

Bridge模式的應(yīng)用一般在兩個(gè)非常強(qiáng)的變化維度,有時(shí)候,即使兩個(gè)維度存在變化,但是變化的地方影響并不大,換而言之兩個(gè)變化不會(huì)導(dǎo)致縱橫交錯(cuò)的結(jié)果,并不一定要使用Bridge模式。

適用場(chǎng)景

如果一個(gè)系統(tǒng)需要在構(gòu)件的抽象化角色和具體化角色之間增加更多的靈活性,避免在兩個(gè)層次之間建立靜態(tài)的聯(lián)系。

設(shè)計(jì)要求實(shí)現(xiàn)化角色的任何改變不應(yīng)當(dāng)影響客戶端,或者說(shuō)實(shí)現(xiàn)化角色的改變對(duì)客戶端是完全透明的。

一個(gè)構(gòu)件有多于一個(gè)的抽象化角色和實(shí)現(xiàn)化角色,系統(tǒng)需要它們之間進(jìn)行動(dòng)態(tài)耦合。

雖然在系統(tǒng)中使用繼承是沒(méi)有問(wèn)題的,但是由于抽象化角色和具體化角色需要獨(dú)立變化,設(shè)計(jì)要求需要獨(dú)立管理這兩者。

相關(guān)模式

裝飾模式橋接模式在一定程度上都是為了減少子類(lèi)的數(shù)目,避免出現(xiàn)復(fù)雜的繼承關(guān)系。但是它們解決的方法卻各有不同,裝飾模式把子類(lèi)中比基類(lèi)中多出來(lái)的部分放到多帶帶的類(lèi)里面,以適應(yīng)新功能增加的需要,當(dāng)我們把描述新功能的類(lèi)封裝到基類(lèi)的對(duì)象里面時(shí),就得到了所需要的子類(lèi)對(duì)象,這些描述新功能的類(lèi)通過(guò)組合可以實(shí)現(xiàn)很多的功能組合.

- 說(shuō)點(diǎn)什么

參考文獻(xiàn):http://blog.csdn.net/zlts000/article/details/26749723
參考文獻(xiàn):https://www.cnblogs.com/houleixx/archive/2008/02/23/1078877.html
參考文件:http://www.cnblogs.com/-crazysnail/p/3977815.html

全文代碼:https://gitee.com/battcn/design-pattern/tree/master/Chapter6/battcn-brideg

個(gè)人QQ:1837307557

battcn開(kāi)源群(適合新手):391619659

微信公眾號(hào):battcn(歡迎調(diào)戲)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/67998.html

相關(guān)文章

  • 設(shè)計(jì)模式在jdk中的應(yīng)用

    摘要:本文只是尋找設(shè)計(jì)模式在中的應(yīng)用。來(lái)補(bǔ)全這一塊工廠模式中的應(yīng)用包線程池解釋和代碼線程池中有線程創(chuàng)建工廠。狀態(tài)模式中的應(yīng)用解釋和代碼根據(jù)一個(gè)指針的狀態(tài)而改變自己的行為適配器模式中的應(yīng)用解釋和代碼將一個(gè)類(lèi)的接口轉(zhuǎn)換成客戶希望的另外一個(gè)接口。 前言 最近重學(xué)設(shè)計(jì)模式,而且還有很多源碼要看。所以就想一舉兩得。從源碼中尋找設(shè)計(jì)模式。順便還可以看看源碼。。。本文只是尋找設(shè)計(jì)模式在java中的應(yīng)用。優(yōu)...

    dingding199389 評(píng)論0 收藏0
  • 編程中的那些套路——關(guān)于橋接模式

    摘要:該文章屬于編程中的那些經(jīng)典套路設(shè)計(jì)模式匯總系列,并且以下內(nèi)容基于語(yǔ)言今天來(lái)談?wù)剺蚪幽J剑瑯蚪幽J降墓δ茉谟趯蓚€(gè)原本不相關(guān)的類(lèi)結(jié)合在一起,然后利用兩個(gè)類(lèi)中的方法和屬性,輸出一份新的結(jié)果。 該文章屬于《編程中的那些經(jīng)典套路——設(shè)計(jì)模式匯總》系列,并且以下內(nèi)容基于語(yǔ)言PHP 今天來(lái)談?wù)剺蚪幽J剑瑯蚪幽J降墓δ茉谟趯蓚€(gè)原本不相關(guān)的類(lèi)結(jié)合在一起,然后利用兩個(gè)類(lèi)中的方法和屬性,輸出一份新的結(jié)果...

    xioqua 評(píng)論0 收藏0
  • java篇 - 收藏集 - 掘金

    摘要:進(jìn)階多線程開(kāi)發(fā)關(guān)鍵技術(shù)后端掘金原創(chuàng)文章,轉(zhuǎn)載請(qǐng)務(wù)必將下面這段話置于文章開(kāi)頭處保留超鏈接。關(guān)于中間件入門(mén)教程后端掘金前言中間件 Java 開(kāi)發(fā)人員最常犯的 10 個(gè)錯(cuò)誤 - 后端 - 掘金一 、把數(shù)組轉(zhuǎn)成ArrayList 為了將數(shù)組轉(zhuǎn)換為ArrayList,開(kāi)發(fā)者經(jīng)常... Java 9 中的 9 個(gè)新特性 - 后端 - 掘金Java 8 發(fā)布三年多之后,即將快到2017年7月下一個(gè)版...

    OpenDigg 評(píng)論0 收藏0
  • JS 橋接模式

    摘要:簡(jiǎn)介橋接模式將抽象部分與它的實(shí)現(xiàn)部分分離,使它們都可以獨(dú)立地變化。同時(shí)橋接模式也有自己的缺點(diǎn)大量的類(lèi)將導(dǎo)致開(kāi)發(fā)成本的增加,同時(shí)在性能方面可能也會(huì)有所減少。 1. 簡(jiǎn)介 橋接模式(Bridge)將抽象部分與它的實(shí)現(xiàn)部分分離,使它們都可以獨(dú)立地變化。其實(shí)就是函數(shù)的封裝,比如要對(duì)某個(gè)DOM元素添加color和backgroundColor,可以封裝個(gè)changeColor函數(shù),這樣可以在多個(gè)...

    chemzqm 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<