一弛姜、介紹,定義
又稱橋梁模式妖枚,結(jié)構(gòu)型設(shè)計(jì)模式廷臼。
承接者連接 兩邊 的作用,兩邊指抽象部分和實(shí)現(xiàn)部分绝页。
將 抽象部分 和 實(shí)現(xiàn)部分 分離荠商,使它們都可以獨(dú)立地進(jìn)行變化。
二续誉、使用場(chǎng)景
對(duì)于不希望使用繼承或因多層次繼承導(dǎo)致系統(tǒng)類的個(gè)數(shù)急劇增加的系統(tǒng)莱没,考慮使用橋接模式。
需要在構(gòu)件的抽象化角色和具體角色之間增加更多靈活性酷鸦,避免兩層次間建立靜態(tài)的繼承關(guān)系饰躲,可通過(guò)橋接模式使它們?cè)诔橄髮咏⒁粋€(gè)關(guān)聯(lián)關(guān)系。
一個(gè)類存在兩個(gè)獨(dú)立變化的維度臼隔,且這兩個(gè)維度都需進(jìn)行擴(kuò)展嘹裂。
任何多維度變化類或多個(gè)樹狀類之間的耦合可通過(guò)橋接模式解耦。
三躬翁、UML類圖
四焦蘑、通用代碼
Abstraction:抽象部分該類保持一個(gè)對(duì)實(shí)現(xiàn)部分對(duì)象的引用盯拱,抽象部分中的方法需要調(diào)用實(shí)現(xiàn)部分的對(duì)象來(lái)實(shí)現(xiàn)盒发。該類一般為抽象類例嘱。
RefinedAbstraction:優(yōu)化的抽象部分抽象部分的具體實(shí)現(xiàn),該類一般是對(duì)抽象部分的方法進(jìn)行完善和擴(kuò)展宁舰。
Implementor:實(shí)現(xiàn)部分可以為接口或抽象類拼卵,其方法不一定要與抽象部分中的一致,一般情況下是由實(shí)現(xiàn)部分提供基本的操作蛮艰,而抽象部分定義的則是基于實(shí)現(xiàn)部分這些基本操作的業(yè)務(wù)方法腋腮。
ConcreteImplementorA/B:實(shí)現(xiàn)部分的具體實(shí)現(xiàn)完成實(shí)現(xiàn)部分中定義的具體邏輯。
// 實(shí)現(xiàn)部分的抽象接口
public interface Implementor {
/** * 實(shí)現(xiàn)抽象部分的具體方法 */
public void operationImpl();
}
// 實(shí)現(xiàn)部分具體的實(shí)現(xiàn)
public class ConcreteImplementorA implements Implementor {
@Override
public void operationImpl() {
// 忽略實(shí)現(xiàn)邏輯
}
}
// 抽象部分
public abstract class Abstraction {
// 聲明一私有成員變量引用實(shí)現(xiàn)部分的對(duì)象
private Implementor mImplementor;
/** * 通過(guò)實(shí)現(xiàn)部分對(duì)象的引用構(gòu)造抽象部分的對(duì)象 *
@param implementor 實(shí)現(xiàn)部分對(duì)象的引用 */
public Abstraction(Implementor implementor) {
mImplementor = implementor;
}
/** * 通過(guò)調(diào)用實(shí)現(xiàn)部分具體的方法實(shí)現(xiàn)具體的功能 */
public void operation() {
mImplementor.operationImpl();
}
}
// 優(yōu)化的抽象部分
public class RefinedAbstraction extends Abstraction {
public RefinedAbstraction(Implementor implementor) {
super(implementor);
}
/** * 對(duì) Abstraction 中的方法進(jìn)行擴(kuò)展 */
public void refinedOperation() {
// 忽略實(shí)現(xiàn)邏輯
}
}
// 客戶端實(shí)現(xiàn)
public class Client {
public static void main(String[] args) {
RefinedAbstraction abstration = new RefinedAbstraction( new ConcreteImplementorA );
abstraction.operation();
abstraction.refinedOperation();
}
}
五壤蚜、簡(jiǎn)單實(shí)現(xiàn)
大家都知道去喝咖啡一般分為四種即寡。大杯加糖,大杯不加糖袜刷,小貝加糖聪富,小杯不加糖,對(duì)于一杯咖啡來(lái)說(shuō)這4中就是兩種變化著蟹,一種是大杯與小杯墩蔓,加糖與不加糖,這兩種變化胡良獨(dú)立變化萧豆。這里就可以用橋接模式奸披。
這里的Coffee.java代表抽象部分Abstraction
public abstract class Coffee {
protected CoffeeAddttives addttives;
public Coffee(CoffeeAddttives addttives) {
super();
this.addttives = addttives;
}
public abstract void makeCoffee();
}
LargeCoffee,SmallCoffee代表 RefinedAbstraction優(yōu)化的抽象部分
public class LargeCoffee extends Coffee {
public LargeCoffee(CoffeeAddttives addttives) {
super(addttives);
}
@Override
public void makeCoffee() {
System.out.println("小杯的" + addttives.addSomething() + "咖啡");
}
}
public class SmallCoffee extends Coffee {
public SmallCoffee(CoffeeAddttives addttives) {
super(addttives);
}
@Override
public void makeCoffee() {
System.out.println("大杯的" + addttives.addSomething() + "咖啡");
}
}
CoffeeAddttives也就是Implementor角色涮雷,實(shí)現(xiàn)部分的抽象接口
/**
* 咖啡添加劑 往咖啡添加糖或者原味
*/
public abstract class CoffeeAddttives {
public abstract String addSomething();
}
Sugar阵面、Ordinary也就是ConcreImplementor角色,
public class Ordinary extends CoffeeAddttives {
@Override
public String addSomething() {
return "原味";
}
}
public class Sugar extends CoffeeAddttives {
@Override
public String addSomething() {
return "加糖";
}
}
客戶端
public class Client {
public static void main(String[] args) {
//準(zhǔn)備原味
Ordinary ordinary = new Ordinary();
//準(zhǔn)備糖
Sugar sugar = new Sugar();
//原味大杯
LargeCoffee largeCoffee = new LargeCoffee(ordinary);
largeCoffee.makeCoffee();
//加糖大杯
largeCoffee = new LargeCoffee(sugar);
largeCoffee.makeCoffee();
//原味小杯
SmallCoffee smallCoffee = new SmallCoffee(ordinary);
smallCoffee.makeCoffee();
//加糖小杯
smallCoffee = new SmallCoffee(sugar);
smallCoffee.makeCoffee();
}
}
小杯的原味咖啡
小杯的加糖咖啡
大杯的原味咖啡
大杯的加糖咖啡
這里的CoffeeAddttives對(duì)應(yīng)的是UML類圖中的實(shí)現(xiàn)部分也就是Implementor角色洪鸭,而Coffee對(duì)應(yīng)抽象部分膜钓,也就是Abstraction角色。
另外模式中定義的“抽象”與“實(shí)現(xiàn)”實(shí)質(zhì)上對(duì)應(yīng)的兩個(gè)獨(dú)立變化為 維護(hù)卿嘲,所以上文才說(shuō)任何維度辯護(hù)A類或者說(shuō)多個(gè)樹狀類之間的耦合都可以使用橋接模式來(lái)實(shí)現(xiàn)解耦颂斜。
這里使用橋接模式也就是將是否加糖與大小杯兩個(gè)維度實(shí)現(xiàn)了解耦。
此時(shí)如果我們想加個(gè)中杯的咖啡拾枣,只需要添加一個(gè)類
public class MiddleCoffee extends Coffee {
public MiddleCoffee(CoffeeAddttives addttives) {
super(addttives);
// TODO Auto-generated constructor stub
}
@Override
public void makeCoffee() {
System.out.println("中杯的" + addttives.addSomething() + "咖啡");
}
}
客戶端稍作修改即可沃疮。添加以下代碼
//原味小杯
MiddleCoffee middleCoffee = new MiddleCoffee(ordinary);
middleCoffee.makeCoffee();
//加糖小杯
middleCoffee = new MiddleCoffee(sugar);
middleCoffee.makeCoffee();
簡(jiǎn)單實(shí)現(xiàn)2
蘋果、聯(lián)想梅肤、戴爾 都有 平板司蔬、筆記本、臺(tái)式機(jī)
由圖可見(jiàn)姨蝴,繼承關(guān)系復(fù)雜俊啼,要新增一個(gè)需要在每個(gè)下面都分別添加,違反單一原則
建立品牌類接口
public interface Brand{
void info();
}
各個(gè)具體品牌:
//聯(lián)想
public class Lenovo implements Brand{
@Override
public void info(){
System.out.println("聯(lián)想");
}
}
//蘋果
public class Apple implements Brand{
@Override
public void info(){
System.out.println("蘋果");
}
}
...
以抽象的電腦類為例
public abstract class Computer{
//組合左医、品牌
protected Brand brand;
public Compluter (Brand brand){
this.brand = brand;
}
public void info(){
brand.info(); //品牌
}
}
具體的桌面電腦
class Desktop extends Computer{
public Desktop(Brand){
super.info();
}
@Override
public void info(){
super.info();
System.out.println("臺(tái)式機(jī)");
}
}
測(cè)試類
puvlic class Test{
public static void main(String []args){
Computer computer = new Laptop(new Apple());
computer.info();
}
}
computer增加不會(huì)影響品牌類
類圖(對(duì)比上面的圖):
六授帕、模式的優(yōu)缺點(diǎn):
橋接模式珊楼,分離抽象與實(shí)現(xiàn)疯坤,其優(yōu)點(diǎn)毋庸置疑抹腿,即靈活的擴(kuò)展以及對(duì)客戶來(lái)說(shuō)透明的是實(shí)現(xiàn)浅浮。但不足之處在于運(yùn)用橋接模式進(jìn)行設(shè)計(jì),是有一定難度的芥映,需多加推敲與研究洲尊。