zoukankan      html  css  js  c++  java
  • GOF23设计模式之桥接模式(bridge)

    一、桥接模式概述

      桥接模式核心要点:

        处理多层继承结构,处理多维度变化的场景,将各个维度设计成独立的继承结构,使各个维度可以独立的扩展在抽象层建立关联。

    二、桥接模式场景提出与存在问题

      商城系统中常见的商品分类,以电脑为类,如何良好的处理商品分类销售的问题?

      这个场景中有两个变化的维度:品牌、电脑类型。

        

      (1)不使用桥接模式时:

      1 /**
      2  * 不适用桥接模式时的电脑产品按照类型和品牌分类
      3  * @author CL
      4  *
      5  */
      6 public interface Computer {
      7     void sale();
      8 }
      9 
     10 /**
     11  * 类型:台式机
     12  * @author CL
     13  *
     14  */
     15 class Desktop implements Computer {
     16 
     17     @Override
     18     public void sale() {
     19         System.out.println("销售台式机");
     20     }
     21     
     22 }
     23 
     24 /**
     25  * 类型:笔记本
     26  * @author CL
     27  *
     28  */
     29 class Laptop implements Computer {
     30 
     31     @Override
     32     public void sale() {
     33         System.out.println("销售笔记本");
     34     }
     35     
     36 }
     37 
     38 /**
     39  * 类型:平板
     40  * @author CL
     41  *
     42  */
     43 class Pad implements Computer {
     44 
     45     @Override
     46     public void sale() {
     47         System.out.println("销售平板电脑");
     48     }
     49     
     50 }
     51 
     52 /**
     53  * 品牌:联想台式机
     54  * @author CL
     55  *
     56  */
     57 class LenovoDesktop extends Desktop {
     58     @Override
     59     public void sale() {
     60         System.out.println("销售联想台式机");
     61     }
     62 }
     63 
     64 /**
     65  * 品牌:联想笔记本
     66  * @author CL
     67  *
     68  */
     69 class LenovoLaptop extends Desktop {
     70     @Override
     71     public void sale() {
     72         System.out.println("销售联想笔记本");
     73     }
     74 }
     75 
     76 /**
     77  * 品牌:联想平板电脑
     78  * @author CL
     79  *
     80  */
     81 class LenovoPad extends Desktop {
     82     @Override
     83     public void sale() {
     84         System.out.println("销售联想平板电脑");
     85     }
     86 }
     87 
     88 /**
     89  * 品牌:戴尔台式机
     90  * @author CL
     91  *
     92  */
     93 class DellDesktop extends Desktop {
     94     @Override
     95     public void sale() {
     96         System.out.println("销售戴尔台式机");
     97     }
     98 }
     99 
    100 /**
    101  * 品牌:戴尔笔记本
    102  * @author CL
    103  *
    104  */
    105 class DellLaptop extends Desktop {
    106     @Override
    107     public void sale() {
    108         System.out.println("销售戴尔笔记本");
    109     }
    110 }
    111 
    112 /**
    113  * 品牌:戴尔平板电脑
    114  * @author CL
    115  *
    116  */
    117 class DellPad extends Desktop {
    118     @Override
    119     public void sale() {
    120         System.out.println("销售戴尔平板电脑");
    121     }
    122 }
    123 
    124 /**
    125  * 品牌:华硕台式机
    126  * @author CL
    127  *
    128  */
    129 class ASUSDesktop extends Desktop {
    130     @Override
    131     public void sale() {
    132         System.out.println("销售华硕台式机");
    133     }
    134 }
    135 
    136 /**
    137  * 品牌:华硕笔记本
    138  * @author CL
    139  *
    140  */
    141 class ASUSLaptop extends Desktop {
    142     @Override
    143     public void sale() {
    144         System.out.println("销售华硕笔记本");
    145     }
    146 }
    147 
    148 /**
    149  * 品牌:华硕平板电脑
    150  * @author CL
    151  *
    152  */
    153 class ASUSPad extends Desktop {
    154     @Override
    155     public void sale() {
    156         System.out.println("销售华硕平板电脑");
    157     }
    158 }

      测试:

     1 /**
     2  * 客户端
     3  * @author CL
     4  *
     5  */
     6 public class Client {
     7     
     8     public static void main(String[] args) {
     9         Computer c1 = new LenovoDesktop();
    10         c1.sale();
    11     }
    12 
    13 }

      控制台输出:

    销售联想台式机

      (2)存在问题

        ① 扩展性问题(类的个数膨胀问题)

         如果要增加一个新的电脑类型,如智能手机,则要增加各个品牌下面的类;

         如果要增加一个新的品牌,也要增加各种电脑类型的类。

        ② 违反了单一职责原则

         一个类有两个职责:品牌+电脑类型。每个类都有两个原因引起变化。

    三、桥接模式应用

      (1)电脑类型维度

     1 /**
     2  * 维度:电脑类型
     3  * @author CL
     4  *
     5  */
     6 public class Computer {
     7     protected Brand brand;
     8 
     9     public Computer(Brand brand) {
    10         this.brand = brand;
    11     }
    12 
    13     public void sale() {
    14         brand.sale();
    15     }
    16 }
    17 
    18 /**
    19  * 台式机
    20  * @author CL
    21  *
    22  */
    23 class Desktop extends Computer {
    24 
    25     public Desktop(Brand brand) {
    26         super(brand);
    27     }
    28     
    29     @Override
    30     public void sale() {
    31         super.sale();
    32         System.out.println("销售台式机");
    33     }
    34 }
    35 
    36 /**
    37  * 笔记本
    38  * @author CL
    39  *
    40  */
    41 class Laptop extends Computer {
    42 
    43     public Laptop(Brand brand) {
    44         super(brand);
    45     }
    46     
    47     @Override
    48     public void sale() {
    49         super.sale();
    50         System.out.println("销售笔记本");
    51     }
    52 }
    53 
    54 /**
    55  * 平板电脑
    56  * @author CL
    57  *
    58  */
    59 class Pad extends Computer {
    60 
    61     public Pad(Brand brand) {
    62         super(brand);
    63     }
    64     
    65     @Override
    66     public void sale() {
    67         super.sale();
    68         System.out.println("销售平板电脑");
    69     }
    70 }

      (2)品牌维度

     1 /**
     2  * 一种维度:品牌
     3  * @author CL
     4  *
     5  */
     6 public interface Brand {
     7     void sale();
     8 }
     9 
    10 /**
    11  * 联想电脑
    12  * @author CL
    13  *
    14  */
    15 class Lenovo implements Brand {
    16 
    17     @Override
    18     public void sale() {
    19         System.out.println("销售联想电脑");
    20     }
    21     
    22 }
    23 
    24 /**
    25  * 戴尔电脑
    26  * @author CL
    27  *
    28  */
    29 class Dell implements Brand {
    30 
    31     @Override
    32     public void sale() {
    33         System.out.println("销售戴尔电脑");
    34     }
    35     
    36 }
    37 
    38 /**
    39  * 华硕电脑
    40  * @author CL
    41  *
    42  */
    43 class ASUS implements Brand {
    44 
    45     @Override
    46     public void sale() {
    47         System.out.println("销售华硕电脑");
    48     }
    49     
    50 }

      (3)测试

     1 /**
     2  * 客户端
     3  * @author CL
     4  *
     5  */
     6 public class Client {
     7     
     8     public static void main(String[] args) {
     9         //销售联想笔记本电脑
    10         Computer  c1 = new Laptop(new Lenovo());
    11         c1.sale();
    12         
    13         //销售戴尔台式机
    14         Computer c2 = new Desktop(new Dell());
    15         c2.sale();
    16     }
    17 
    18 }

      控制台输出:

    销售联想电脑
    销售笔记本
    销售戴尔电脑
    销售台式机

      (4)假如现在要在品牌维度上增加一种品牌:宏碁电脑,只需要在品牌维度中增加如下代码:

     1 /**
     2  * 宏碁电脑
     3  * @author CL
     4  *
     5  */
     6 class Acer implements Brand {
     7 
     8     @Override
     9     public void sale() {
    10         System.out.println("销售宏碁电脑");
    11     }
    12     
    13 }

      (5)测试

     1 /**
     2  * 客户端
     3  * @author CL
     4  *
     5  */
     6 public class Client {
     7     
     8     public static void main(String[] args) {
     9         //销售联想笔记本电脑
    10         Computer  c1 = new Laptop(new Lenovo());
    11         c1.sale();
    12         
    13         //销售戴尔台式机
    14         Computer c2 = new Desktop(new Dell());
    15         c2.sale();
    16         
    17         //销售宏碁的平板电脑
    18         Computer c3 = new Pad(new Acer());
    19         c3.sale();
    20     }
    21 
    22 }

      控制台输出:

    销售联想电脑
    销售笔记本
    销售戴尔电脑
    销售台式机
    销售宏碁电脑
    销售平板电脑

    四、桥接模式总结

      (1)桥接模式可以取代多层继承的方案。

          多层继承违背了单一职责原则,复用性较差,类的个数也非常多。桥接模式可以极大的减少子类的个数,从而降低管理和维护的成本。

      (2)桥接模式极大的提高了系统的可扩展性。

          在两个变化的维度中任意扩展一个维度。都不需要修改原有的代码,符合开闭原则。

    五、桥接模式实际开发中的应用场景

      (1)JDBC驱动程序;

      (2)AWT中的Peer框架;

      (3)人力资源系统中的奖金计算模块:

          奖金分类:个人奖金、团队奖金、激励奖金

          部门分类:开发部门、运维部门、人事部门

      (4)OA系统中的消息处理:

          业务类型:普通消息、加密消息、紧急消息

          发送方式:系统内部、手机短信、邮件、飞秋

      (5)…………

  • 相关阅读:
    ubuntu开启SSH服务
    [FreeModbus源码分析] 1.协议简介
    minicom无法输入问题
    Redis学习sorted set数据类型
    Redis学习string数据类型
    Redis学习list数据类型
    Redis学习常用命令
    Redis学习hash数据类型
    Redis学习set数据结构
    Redis初探Redis安装
  • 原文地址:https://www.cnblogs.com/cao-lei/p/8304078.html
Copyright © 2011-2022 走看看