一、引出桥接模式
假设我们现在有一个项目,这个项目列就是我们是生产遥控器的厂商,承接各种遥控器的生产,比如我们现在承接的有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();*/
- }
- }
三、总结
当系统有多维度角度分类的时候,而每一种分类又有可能的变化,考虑使用桥接模式。桥接的目的是分离抽象与实现,使抽象和实现可以独立变化。
和策略模式的差异:
桥接的目的是让底层实现和上层接口可以分别演化,从而提高移植性
策略的目的是将复杂的算法封装起来,从而便于替换不同的算法。
桥接是往往是为了利用已有的方法或类
策略是为了扩展和修改,并提供动态配置
桥接强调接口对象仅仅提供基本的操作
策略强调接口对象提供的是这一种算法
来源: http://www.cnblogs.com/pony1223/p/7530721.html