JAVA設計模式:橋接模式


 聲明:轉載請說明來源:http://www.cnblogs.com/pony1223/p/7530721.html

一、引出橋接模式

假設我們現在有一個項目,這個項目列就是我們是生產遙控器的廠商,承接各種遙控器的生產,比如我們現在承接的有LG、索尼的電視廠商的,那如果我們現在要設計的話,我們首先想到的最簡單的方式就是如下的方式:

 

對上述類圖作下解釋:各大電視機廠商對外提供的一般都是統一接口,以便大家直接操作電視的時候,也就是我們通常如果遙控器丟失的時候,可以直接去按電視機下面的按鈕進行直接操作,基本都是一樣的,就是因為實現了統一的接口,但因為各自的采用的協議或者算法的不同,因此實現類是不一樣的,那么這個時候對於遙控器生產廠商而言要做的,首先要對外是一致的,這樣方便操作,但同時又需要去調用各大電視機廠商的實現類,那么最容易的就是繼承各個實現類,同時實現自己的接口去做了,於是代碼產生如下:

1.電視機廠商的接口:

public interface Control {
    
    public void On();
    public void Off();
    public void setChannel(int ch);
    public void setVolume(int vol);

}

 

2.LG 索尼公司自己的實現類

package study.designmode.bridgemode.control;

public class LGControl implements Control {

    @Override
    public void On() {
        // TODO Auto-generated method stub
        System.out.println("**Open LG TV**");
    }

    @Override
    public void Off() {
        // TODO Auto-generated method stub
        System.out.println("**Off LG TV**");
    }

    @Override
    public void setChannel(int ch) {
        // TODO Auto-generated method stub
        System.out.println("**The LG TV Channel is setted "+ch+"**");
    }

    @Override
    public void setVolume(int vol) {
        // TODO Auto-generated method stub
        System.out.println("**The LG TV Volume is setted "+vol+"**");
    }

}



package study.designmode.bridgemode.control;

public class SonyControl implements Control {

    @Override
    public void On() {
        // TODO Auto-generated method stub
        System.out.println("*Open Sony TV*");
    }

    @Override
    public void Off() {
        // TODO Auto-generated method stub
        System.out.println("*Off Sony TV*");
    }

    @Override
    public void setChannel(int ch) {
        // TODO Auto-generated method stub
        System.out.println("*The Sony TV Channel is setted "+ch+"*");
    }

    @Override
    public void setVolume(int vol) {
        // TODO Auto-generated method stub
        System.out.println("*The Sony TV Volume is setted "+vol+"*");
    }

}

 

3.遙控器廠商的接口

package study.designmode.bridgemode;

public interface TvControl {
    public void Onoff();
    public void  nextChannel();
    public void  preChannel();
}

 

4.實現類:

package study.designmode.bridgemode;

import study.designmode.bridgemode.control.LGControl;

public class LGTvControl extends LGControl implements TvControl{
    private static int ch=0;
    private static boolean ison=false;
    public void Onoff()
    {
        if(ison)
        {
            ison=false;
            super.Off();
        }else{
            ison=true;
            super.On();
        }
    }
    public void nextChannel()
    {
        ch++;
        super.setChannel(ch);
    }
    public void preChannel()
    {
        ch--;
        if(ch<0)
        {
            ch=200;
        }
        super.setChannel(ch);
    }

}

 

package study.designmode.bridgemode;

import study.designmode.bridgemode.control.SonyControl;

public class SonyTvControl extends SonyControl implements TvControl{
    private static int ch=0;
    private static boolean ison=false;
    public void Onoff()
    {
        if(ison)
        {
            ison=false;
            super.Off();
        }else{
            ison=true;
            super.On();
        }
    }
    public void nextChannel()
    {
        ch++;
        super.setChannel(ch);
    }
    public void preChannel()
    {
        ch--;
        if(ch<0)
        {
            ch=200;
        }
        super.setChannel(ch);
    }

}

 

5.測試:

package study.designmode.bridgemode;


public class MainTest {
    public static void main(String[] args) {
        LGTvControl mLGTvControl=new LGTvControl();
        SonyTvControl mSonyTvControl=new SonyTvControl();
        
        mLGTvControl.Onoff();
        mLGTvControl.nextChannel();
        mLGTvControl.nextChannel();
        mLGTvControl.preChannel();
        mLGTvControl.Onoff();
        
        mSonyTvControl.Onoff();
        mSonyTvControl.preChannel();
        mSonyTvControl.preChannel();
        mSonyTvControl.preChannel();
        mSonyTvControl.Onoff();
    }


}

結果:

 

思考帶來的問題:如果我現在要新增承接一個電視廠商夏普的,那么這個時候我需要再實現一個類,然后繼承自夏普的實現類,那么帶來的問題就是每增加一個電視機廠商的活,那么遙控器廠商就生成一個遙控器的實現類,如果遙控器想要對外界的接口發生以下變化,那么所有的實現類也要變化;也就是遙控器廠商和電視機廠商之間是緊密關聯在一起的,沒法獨立開來,你電視器廠商增加一個,我就要增加一個;拿就是一種N*N的關系,有沒有辦法做到1*N;就是你電視器廠商的變化,我遙控器廠商不去變化,但可以滿足要求,統一一個來實現呢?拿就是橋接模式了。

 

二、解決辦法

要解決上面的問題,首先我們需要分析變化和不變化的部分,上面的需求可以看出,變化的應該是電視機廠商部分,但電視廠商已經統一化了,那么根據以往的經驗我們要少用繼承,多用組合,如果我們采用組合方式來解決呢,類圖如下:

從上述可以看出,滿足了我們的1*n的想法,這也橋接模式的意義所在。

橋接模式:將實現與抽象放在兩個不同的類層次中,使兩個層次可以獨立改變。(這里的抽象就是我們遙控器廠商,實現就是我們的電視機廠商)

代碼實現如下:

1.抽象類

 

package study.designmode.bridgemode.bridge;

import study.designmode.bridgemode.control.Control;

public abstract class TvControlabs {

      Control mControl=null;
    public TvControlabs(Control mControl)
    {
        this.mControl=mControl;
    }
    
    public abstract void Onoff();
    public abstract void nextChannel();
    public abstract void preChannel();
    
    
}

 

2.實現類:

package study.designmode.bridgemode.bridge;

import study.designmode.bridgemode.control.Control;

public class TvControl extends TvControlabs {
    private  int ch=0;
    private  boolean ison=false;
    
    public TvControl(Control mControl)
    {
        super(mControl);
    }
    @Override
    public void Onoff() {
        // TODO Auto-generated method stub

        if(ison)
        {
            ison=false;
            mControl.Off();
        }else{
            ison=true;
            mControl.On();
        }
    
    }

    @Override
    public void nextChannel() {
        // TODO Auto-generated method stub

        ch++;
        mControl.setChannel(ch);
    
    }

    @Override
    public void preChannel() {
        // TODO Auto-generated method stub

        ch--;
        if(ch<0)
        {
            ch=200;
        }
        mControl.setChannel(ch);
    
    }

}

3.測試:

package study.designmode.bridgemode.bridge;

import study.designmode.bridgemode.control.LGControl;
import study.designmode.bridgemode.control.SharpControl;
import study.designmode.bridgemode.control.SonyControl;



public class MainTest {
    public static void main(String[] args) {
        TvControl mLGTvControl;
        TvControl mSonyTvControl;
        mSonyTvControl=new TvControl(new SonyControl());
        mLGTvControl=new TvControl(new LGControl());
        mLGTvControl.Onoff();
        mLGTvControl.nextChannel();
        mLGTvControl.nextChannel();
        mLGTvControl.preChannel();
        mLGTvControl.Onoff();
        
        mSonyTvControl.Onoff();
        mSonyTvControl.preChannel();
        mSonyTvControl.preChannel();
        mSonyTvControl.preChannel();
        mSonyTvControl.Onoff();
        
    /*    newTvControl mSharpTvControl;
        mSharpTvControl=new newTvControl(new SharpControl());
        mSharpTvControl.Onoff();
        mSharpTvControl.nextChannel();
        mSharpTvControl.setChannel(9);
        mSharpTvControl.setChannel(28);
        mSharpTvControl.Back();
        mSharpTvControl.Onoff();*/
        
    }


}

 

三、總結

當系統有多維度角度分類的時候,而每一種分類又有可能的變化,考慮使用橋接模式。橋接的目的是分離抽象與實現,使抽象和實現可以獨立變化。
和策略模式的差異:
橋接的目的是讓底層實現和上層接口可以分別演化,從而提高移植性
策略的目的是將復雜的算法封裝起來,從而便於替換不同的算法。

橋接是往往是為了利用已有的方法或類
策略是為了擴展和修改,並提供動態配置

橋接強調接口對象僅僅提供基本的操作
策略強調接口對象提供的是這一種算法

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM