zoukankan      html  css  js  c++  java
  • Java设计模式——桥模式

    概述

    桥模式(Bridge)是为了解决将抽象部分与实现部分分离,好让他们都在自己的维度上有多维度地变化。这句话是好理解的,只是我在学习完桥模式之后,存在一些疑问,还好现在想通了。现在我就桥模式的设计思想和我的疑问一并发出,希望于你有益。


    版权说明

    著作权归作者所有。
    商业转载请联系作者获得授权,非商业转载请注明出处。
    本文作者:Coding-Naga
    发表日期: 2016年3月31日
    本文链接:http://blog.csdn.net/lemon_tree12138/article/details/51024127
    来源:CSDN
    更多内容:分类 >> 设计模式


    场景

    现假设市面上有多种不同型号的电视机,和一些不同的遥控器生产产商。遥控器生产产商要为这些电视机进行生产遥控器,可是这些电视机型号太多,有一些电视机的型号太杂,甚至在后期会出现一些不同型号的电视机。


    普通聚合方案

    在这个一般方案中,遥控器产商要为每一种电视机生产一种遥控器。类图如下
    这里写图片描述
    每个具体的遥控器都去继承或是实现遥控器的抽象或是接口,并且在每个具体的遥控器内部都聚合了各自的电视机接口。这种方案可以解决问题,可以解决遥控器与电视机的对应关系。可是,却有一个问题,就像上面场景中所说的,如果这里的有一些新的电视机出现,那么生产遥控器的产商还得去生产新的遥控器。这样一来各自的遥控器数量不但不好把握,而且这样的设计很繁杂。


    桥模式

    上面一般的聚合方案无法解决遥控器的一般性,对于新的机型无法兼容和适应。对于这样在抽象或是实现上会有多维度扩展的情况,我们就必须重新设计代码结构了。下面是桥模式,以及桥模式是如何解决这个问题的。

    定义

    将抽象部分(Abstraction)与实现部分(Implementor)分离,使它们可以独立地变化。

    分析

    桥模式的应用场景是某一个抽象或是实现可能存在多维度的变化。就像上面的遥控器实例,我们在遥控器这个抽象上,可能会有不同的生产产商;在电视机这个实现上可能会RCA、Sony等等。桥模式可以让遥控器的抽象和电视机的实现在各自的方向上多维度变化,而不用关心其他的事情。
    在上面我也分析了一般的聚合方案是不可靠的,它的确可以解决一些问题,可是却是繁琐的,也是不必要的。
    这里再说一个大家可能都比较熟悉的例子。比如我们现在编写的Java程序,与运行平台之间的关系。我们可以有很多很多的Java程序,而运行平台也可以是Windows、Linux或是Mac。我们的Java程序需要在所有的平台上能够执行,每一个平台也要保证能够全部的Java程序。

    类图

    这里我们让遥控器的抽象类聚合电视机的接口。因为所以的电视都实现电视机这个接口,那么遥控器的抽象类也就聚合了所有的电视机实现。这样不管你电视机的型号如何改变,遥控器都可以不做修改也能继续工作。
    这里写图片描述
    注:当时我在这里存在一个小疑问,为什么我们的电视机接口不是聚合到遥控器的子类中,而是聚合到遥控器的抽象类中呢?也就是说,这里我有没有必要有一个遥控器的抽象类?
    现在我假设这里不存在这个RemoteControl的抽象类,那么ConcreteRemote将持有TV这个接口,可是这样在遥控器这个维度上都不好扩展了。桥模式的牛X之处就在于它可以让多维度的抽象和实现都可以在多维度上进行任意扩展。

    逻辑实现

    基于上面的类图,可编写Java代码。

    TV.java

    public interface TV {
        public void on();
        public void off();
        public void tuneChannel(int channel);
    }

    RCA.java

    public class RCA implements TV {
    
        @Override
        public void on() {
            System.out.println("RCA被打开了");
        }
    
        @Override
        public void off() {
            System.out.println("RCA被关闭了");
        }
    
        @Override
        public void tuneChannel(int channel) {
            System.out.println("切换到第" + channel + "频道了");
        }
    }

    Sony.java

    public class Sony implements TV {
    
        @Override
        public void on() {
            System.out.println("Sony被打开了");
        }
    
        @Override
        public void off() {
            System.out.println("Sony被打开了");
        }
    
        @Override
        public void tuneChannel(int channel) {
            System.out.println("切换到第" + channel + "频道了");
        }
    }

    RemoteControl.java

    public abstract class RemoteControl {
    
        protected TV tv = null;
    
        public RemoteControl(TV _tv) {
            this.tv = _tv;
        }
    
        public abstract void on();
    
        public abstract void off();
    
        public void setChannel(int channel) {
            if (tv != null) {
                tv.tuneChannel(channel);
            }
        }
    }

    ConcreteRemote.java

    public class ConcreteRemote extends RemoteControl {
    
        private int currentStation = 0;
        private final int MAX_STATION = 25;
    
        public ConcreteRemote(TV _tv) {
            super(_tv);
        }
    
        @Override
        public void on() {
            tv.on();
        }
    
        @Override
        public void off() {
            tv.off();
        }
    
        public void setChannel(int channel) {
            currentStation = channel;
            super.setChannel(currentStation);
        }
    
        public void nextChannel() {
            currentStation = (MAX_STATION + currentStation + 1) % MAX_STATION;
            super.setChannel(currentStation);
        }
    
        public void previousChannel() {
            currentStation = (MAX_STATION + currentStation - 1) % MAX_STATION;
            super.setChannel(currentStation);
        }
    }

    模式评价

    优点 缺点
    电视机的实现被解耦,它和遥控器之间不再永久绑定 相对比较复杂
    遥控器和电视机可以独立扩展,且不会影响对方

    Ref

    • 《Head First设计模式》

    Github源码链接

    https://github.com/William-Hai/DesignPatternCollections


  • 相关阅读:
    Comparable内部比较器 和 Comparator外部比较器
    java——包装类数据缓存 ==号详解
    java——包装类中的equals方法
    Eclipse怎么改变@author 姓名
    非常简约学生管理系统——HashSet进行编写
    TreeMap——实现comparable接口并重写CompareTo方法
    flume收集日志直接sink到oracle数据库
    大文件多个服务器复制拷贝
    oracle创建用户表空间
    缓存策略:redis缓存之springCache
  • 原文地址:https://www.cnblogs.com/fengju/p/6336001.html
Copyright © 2011-2022 走看看