JAVA设计模式:桥接模式

Posted 屌丝码农

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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();*/
        
    }


}

 

三、总结

当系统有多维度角度分类的时候,而每一种分类又有可能的变化,考虑使用桥接模式。桥接的目的是分离抽象与实现,使抽象和实现可以独立变化。
和策略模式的差异:
桥接的目的是让底层实现和上层接口可以分别演化,从而提高移植性
策略的目的是将复杂的算法封装起来,从而便于替换不同的算法。

桥接是往往是为了利用已有的方法或类
策略是为了扩展和修改,并提供动态配置

桥接强调接口对象仅仅提供基本的操作
策略强调接口对象提供的是这一种算法

 

以上是关于JAVA设计模式:桥接模式的主要内容,如果未能解决你的问题,请参考以下文章

Java设计模式:桥接模式

JAVA SCRIPT设计模式--结构型--设计模式之Bridge桥接模式

Java设计模式之——桥接模式

图解Java设计模式之桥接模式

java设计模式之桥接模式

Java设计模式-桥接模式