zoukankan      html  css  js  c++  java
  • Java设计模式13:常用设计模式之桥接模式(结构型模式)

    1. Java之桥接模式(Bridge Pattern)

    (1)概述:

    首先我们说一个生活中的例子:

          就拿汽车在路上行驶的来说。即有小汽车又有公共汽车,它们都不但能在市区中的公路上行驶,也能在高速公路上行驶。这你会发现,对于交通工具(汽车)有不同的类型,然而它们所行驶的环境(路)也在变化,在软件系统中就要适应两个方面的变化?怎样实现才能应对这种变化呢 ?

          如何利用面向对象的技术来使得该类型能够轻松的沿着多个方向进行变化,而又不引入额外的复杂度 ? 这就要使用Bridge模式。

    (2)桥接模式的意图:

    桥接模式是用于“把抽象和实现分开,这样它们就能独立变化”。 桥接模式使用了封装、聚合,可以用继承将不同的功能拆分为不同的类。

    2. 桥接模式UML图:

    3. 桥接模式代码实现:

    (1)Implementor : 定义实现接口

    1 interface Implementor {
    2     // 实现抽象部分需要的某些具体功能
    3     public void operationImpl();
    4 }

    (2)Abstraction : 定义抽象接口

     1 abstract class Abstraction {
     2 
     3     // 持有一个 Implementor 对象,形成聚合关系
     4     protected Implementor implementor;
     5   
     6     public Abstraction(Implementor implementor) {
     7         this.implementor = implementor;
     8     }
     9    
    10     // 可能需要转调实现部分的具体实现
    11     public void operation() {
    12         implementor.operationImpl();
    13     }
    14 
    15 }

    (3)ConcreteImplementor :  实现 Implementor 中定义的接口

     1 class ConcreteImplementorA implements Implementor {
     2     @Override
     3     public void operationImpl() {
     4         // 真正的实现
     5         System.out.println("具体实现A");
     6     }    
     7 }
     8 
     9 
    10 class ConcreteImplementorB implements Implementor {
    11     @Override
    12     public void operationImpl() {
    13         // 真正的实现
    14         System.out.println("具体实现B");
    15     }    
    16 }

    (4)RefinedAbstraction : 扩展 Abstraction 类

     1 class RefinedAbstraction extends Abstraction {
     2 
     3     public RefinedAbstraction(Implementor implementor) {
     4         super(implementor);
     5     }
     6     public void otherOperation() {
     7         // 实现一定的功能,可能会使用具体实现部分的实现方法,
     8         // 但是本方法更大的可能是使用 Abstraction 中定义的方法,
     9         // 通过组合使用 Abstraction 中定义的方法来完成更多的功能。
    10     }
    11 }

    (5)测试代码:

    1 public class BridgePattern {
    2     public static void main(String[] args) {
    3         Implementor implementor = new ConcreteImplementorA();
    4         RefinedAbstraction abstraction = new RefinedAbstraction(implementor);
    5         abstraction.operation();
    6         abstraction.otherOperation();
    7     }
    8 }

    运行结果:

    1 具体实现A
    2 其他操作

    4.  桥接模式应用场景

    1)如果你不希望在抽象和实现部分采用固定的绑定关系,可以采用桥接模式,来把抽象和实现部分分开,然后在程序运行期间来动态的设置抽象部分需要用到的具体的实现,还可以动态切换具体的实现。


    2)如果出现抽象部分和实现部分都应该可以扩展的情况,可以采用桥接模式,让抽象部分和实现部分可以独立的变化,从而可以灵活的进行单独扩展,而不是搅在一起,扩展一边会影响到另一边。


    3)如果希望实现部分的修改,不会对客户产生影响,可以采用桥接模式,客户是面向抽象的接口在运行,实现部分的修改,可以独立于抽象部分,也就不会对客户产生影响了,也可以说对客户是透明的。


    4)如果采用继承的实现方案,会导致产生很多子类,对于这种情况,可以考虑采用桥接模式,分析功能变化的原因,看看是否能分离成不同的纬度,然后通过桥接模式来分离它们,从而减少子类的数目。

    5. 桥接模式的应用案例:

    (1)桥接模式的故事:

       电视和遥控器(图中有错字)是一个完美展示两层抽象的例子。你有一个电视机的接口,还有一个遥控器的抽象类。我们都知道,将它们中任何一个定义为一个具体类都不是好办法,因为其它厂家会有不同的实现方法。

    (2)桥接模式Java示例代码:

    首先定义电视机的接口:ITV

    1 public interface ITV {
    2     public void on();
    3     public void off();
    4     public void switchChannel(int channel);
    5 }

    实现ITV 接口的三星电视机

     1 public class SamsungTV implements ITV {
     2     @Override
     3     public void on() {
     4         System.out.println("Samsung is turned on.");
     5     }
     6  
     7     @Override
     8     public void off() {
     9         System.out.println("Samsung is turned off.");
    10     }
    11  
    12     @Override
    13     public void switchChannel(int channel) {
    14         System.out.println("Samsung: channel - " + channel);
    15     }
    16 }

    实现ITV 接口的索尼电视机

     1 public class SonyTV implements ITV {
     2  
     3     @Override
     4     public void on() {
     5         System.out.println("Sony is turned on.");
     6     }
     7  
     8     @Override
     9     public void off() {
    10         System.out.println("Sony is turned off.");
    11     }
    12  
    13     @Override
    14     public void switchChannel(int channel) {
    15         System.out.println("Sony: channel - " + channel);
    16     }
    17 }

    下面是遥控器的抽象类,而且这个遥控器要包含对TV的引用,这样就起到了"桥梁"的作用:连接"抽象部分" 和 "实现部分".

     1 public abstract class AbstractRemoteControl {
     2     /**
     3      * @uml.property  name="tv"
     4      * @uml.associationEnd  
     5      */
     6     private ITV tv;
     7  
     8     public AbstractRemoteControl(ITV tv){
     9         this.tv = tv;
    10     }
    11  
    12     public void turnOn(){
    13         tv.on();
    14     }
    15  
    16     public void turnOff(){
    17         tv.off();
    18     }
    19  
    20     public void setChannel(int channel){
    21         tv.switchChannel(channel);
    22     }
    23 }

    定义遥控器的具体类

     1 public class LogitechRemoteControl extends AbstractRemoteControl {
     2  
     3     public LogitechRemoteControl(ITV tv) {
     4         super(tv);
     5     }
     6  
     7     public void setChannelKeyboard(int channel){
     8         setChannel(channel);
     9         System.out.println("Logitech use keyword to set channel.");
    10     }
    11 }

    测试类:

    1 public class Main {
    2     public static void main(String[] args){
    3         ITV tv = new SonyTV();
    4         LogitechRemoteControl lrc = new LogitechRemoteControl(tv);
    5         lrc.setChannelKeyboard(100);    
    6     }
    7 }

    输出结果,如下:

    Sony: channel – 100
    Logitech use keyword to set channel.

    总结一下, 桥接模式允许两层实现的抽象,上面的电视机和遥控器就是很好的例子。可见,桥接模式提供了更多的灵活性。

  • 相关阅读:
    18.12.30 【sssx】Trie图
    18.12.30 【sssx】线段树
    18.12.25 POJ 1039 Pipe
    18.12.25 POJ 3525 Most Distant Point from the Sea(半平面+二分)
    18.12.25 POJ 1228 Grandpa's Estate
    18.12.22 luogu P3047 [USACO12FEB]附近的牛Nearby Cows
    18.12.21 DSA 中缀表达式的值
    18.12.21 luogu P3650 [USACO1.3]滑雪课程设计Ski Course Design
    18.12.21 【USACO】Times17
    18.12.20 DSA Full Tank?(DP+BFS)
  • 原文地址:https://www.cnblogs.com/hebao0514/p/4934078.html
Copyright © 2011-2022 走看看