zoukankan      html  css  js  c++  java
  • 设计模式:桥接模式及代码示例、桥接模式在jdbc中的体现、注意事项


    0、背景


    加入一个手机分为多种款式,不同款式分为不同品牌。这些详细分类下分别进行操作。

    如果传统做法,需要将手机,分为不同的子类,再继续分,基本属于一个庞大的多叉树,然后每个叶子节点进行相同名称、但是细节不同的功能实现。

    问题

    1. 类爆炸:类的增加基本没有任何优化,多一个就要妥妥的增加类;
    2. 违反单一原则:增加一个品牌,影响每种类型下的这个品牌,增加一个类型,影响每个品牌的这个类型。

    一、桥接模式


    解决上面说的问题的方式就是使用桥接模式。

    桥接(Bridge)模式是指,将实现和抽象放在两个不同的类层次中,使得两个层次可以独立改变。

    桥接模式是一种结构型设计模式,基于类的最小设计原则,让不同的类承担不同的职责。(单一原则)

    桥接模式的主要特点是,把抽象 Abstraction 和行为实现 Implementation 分离开,从而保持各部分的独立和应对他们的功能扩展。

    类图如下所示:

    其中,承担 桥接功能 的抽象类就是 Abstraction。

    看起来还是很抽象,结合上面的手机问题,画出对应的类图,再结合来看:

    也就是说,比起原来的树状结构,用桥接模式,将行为实现放在一边,有自己的接口;将抽象出的另一个维度放在一边,有自己的抽象父类和子类,然后将上层的抽象类和实现接口相关联。

    这样的话,前面遇到的问题:

    • 添加手机样式,就在左边添加抽象类定义就可以;
    • 添加品牌,在右边添加实现类就可以。
    • 其他部分都不会被影响。

    观察上面的图,桥接的意味也很明显,当 QuanPingPhone 使用一个 call 方法的时候,继承的其实是父类的方法,而这里面组合了另一个性质,比如是 Oppo 手机的 call 方法,那么就是通过桥接一路引过去的。 (忽略我的英语)

    按照这个思路我们来写一个实现:

    /*
        品牌,接口
    */
    public interface Brand {
        void open();
        void close();
        void call();
    }
    
    public class Xiaomi implements Brand{
        @Override
        public void open() {
            System.out.println("小米手机开机");
        }
        @Override
        public void close() {
            System.out.println("小米手机关机");
        }
        @Override
        public void call() {
            System.out.println("小米手机打电话");
        }
    }
    
    public class Vivo implements Brand{
        @Override
        public void open() {
            System.out.println("vivo手机开机");
        }
        @Override
        public void close() {
            System.out.println("vivo手机关机");
        }
        @Override
        public void call() {
            System.out.println("vivo手机打电话");
        }
    }
    
    /*
        抽象层:手机,通过品牌接口聚合不同品牌
    */
    public abstract class Phone {
        //品牌
        private Brand brand;
    
        public Phone(Brand brand) {
            this.brand = brand;
        }
        protected void open(){
            this.brand.open();
        }
        protected void close(){
            this.brand.close();
        }
        protected void call(){
            this.brand.call();
        }
    }
    
    /*
        折叠手机,继承抽象类手机
    */
    public class BoldPhone extends Phone{
        //构造器
        public BoldPhone(Brand brand) {
            super(brand);
        }
        public void open(){
            super.open();//实际上通过父类的open,桥接到了brand下面的某个子类的open
            System.out.println("打开的是折叠手机");
        }
        public void close(){
            super.close();
            System.out.println("关闭的是折叠手机");
        }
        public void call(){
            super.call();
            System.out.println("打电话的的是折叠手机");
    
    
        }
    }
    
    /*
        全面屏手机,继承抽象类手机
    */
    public class ScreenPhone extends Phone{
        public ScreenPhone(Brand brand) {
            super(brand);
        }
        public void open(){
            super.open();//实际上通过父类的open,桥接到了brand下面的某个子类的open
            System.out.println("打开的是全面屏手机");
        }
        public void close(){
            super.close();
            System.out.println("关闭的是全面屏手机");
        }
        public void call(){
            super.call();
            System.out.println("打电话的的是全面屏手机");
        }
    }
    

    调用试试:

    /*
        客户端
    */
    public class Client {
        public static void main(String[] args) {
            //获取一个手机,需要的是样式+手机两个实现类
            //通过Phone这个抽象类,增加一个样式为BoldPhone的手机,桥接到品牌为Xiaomi
            Phone phone = new BoldPhone(new Xiaomi());
            phone.open();
            phone.call();
            phone.close();
        }
    }
    

    这样的话,如果扩展起来,比如新增加一种样式的手机,我们只需要继承Phone再写一个子类,其余都不需要更改,如果新增加一个品牌的手机,只需要实现Band接口再写一个实现类,其余都不需要更改。


    二、使用桥接模式的源码:JDBC


    JDBC 源码里:

    MySQL 的 Connection 接口实现的是 java.sql.Connection 接口,同时 Oracle 数据库也一样可以实现 java.sql.Connection 接口,他们向下都可以有更多的实现子类。

    然后 DriverManager 相当于桥接模块,依赖和聚合 java.sql.Connection 接口,供客户端调用。

    和我们上面所说的略微不同,就是 DriverManager 不是抽象类,而是直接的具体实现。


    三、桥接模式的注意事项


    1. 桥接模式实现了抽象和实现部分的分离,提高了系统的灵活性,让抽象部分和实现部分独立开来,有助于系统的分层设计。
    2. 高层只需要知道抽象部分和实现部分的接口,而不需要知道其他具体实现;
    3. 替代了多层继承,大大减少了子类的数量;
    4. 桥接模式的引入,增加了系统的设计和理解难度,由于聚合关联关系建立在抽象层,要求开发者针能对抽象层进行设计和编程;
    5. 适用范围有局限性

    应用场景:

    1. jdbc:多种驱动,多种数据库;
    2. 银行转账:因为转账动作要分很多类,用户也分很多类,所以他们之间不适合多层继承;
    3. 消息管理:消息类型不同,消息传送方式不同。
  • 相关阅读:
    c# 菱形,三角形
    c#判断一个时间的时间段
    c# 1,判断是否为正整数 2 判断体重
    数据库 基础
    c#100 计算行李重量
    c#基础 1,100以内的与7相关的数字;2,计算器,
    String 类;Math 类
    常用的C#类
    冒泡排序与快速排序
    数据库基本知识
  • 原文地址:https://www.cnblogs.com/lifegoeson/p/13507883.html
Copyright © 2011-2022 走看看