• 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();*/
            
        }
    
    
    }

    三、总结

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

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

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

  • 相关阅读:
    elasticsearch query 和 filter 的区别
    java 模拟简单搜索
    filterBuilders 构建过滤器query
    elasticsearch java 索引操作
    lesson4:利用jmeter来压测数据库
    lesson3:使用java代码的方式对不能识别的协议进行压力测试
    lession2:使用HTTP Cookie 管理器来传递cookies值
    lesson1:压测普通网页
    php mysql find_in_set函数 检索单子段 逗号分隔序列
    写出一种排序算法(要写出代码),并说出优化它的方法。(新浪面试题)
  • 原文地址:https://www.cnblogs.com/pony1223/p/7530721.html
Copyright © 2020-2023  润新知