• 设计模式之桥接模式


    桥接模式

    概述

    桥接模式:Decouple an abstraction from its implementation so that the two can vary independently.(将抽象和实现解耦,使得两者可以独立地变化。而不会直接影响到其他部分。

    UML

    • Abstraction:

      抽象部分的接口。通常在这个对象里面,要维护一个实现部分的对象引用,在抽象对象里面的方法,需要调用实现部分的对象来完成。这个对象里面的方法,通常都是跟具体的业务相关的方法。

    • RefinedAbstraction:

      扩展抽象部分的接口,通常在这些对象里面,定义跟实际业务相关的方法,这些方法的实现通常会使用Abstraction中定义的方法,也可能需要调用实现部分的对象来完成。

    • Implementor:

      定义实现部分的接口,这个接口不用和Abstraction里面的方法一致(根据约定优于配置原则,建议跟Abstraction一致。),通常是由Implementor接口提供基本的操作,而Abstraction里面定义的是基于这些基本操作的业务方法,也就是说Abstraction定义了基于这些基本操作的较高层次的操作。

    • ConcreteImplementor:

      真正实现Implementor接口的对象。

    使用场景:

    ● 不希望或不适用使用继承的场景

    ● 接口或抽象类不稳定的场景

    ● 重用性要求较高的场景

    示例

    未使用桥接模式的抽象与实现结构图(如下):


    如果要增加一个apple品牌的电脑,则需要在台式机下新增一个apple的台式机

    在笔记本下新增一个apple笔记本,在pad下新增一个apple的pad。代码比较繁琐。

    如果使用桥接模式(如下图),使抽象部分和抽象的派生(实现)部分分离出来,这样让它们各自的变化,这样每种实现就不会影响到其他实现。从而达到对应变化的目的

    将电脑类型作为一个维度,将品牌也做为一个维度。两个维度独立起来,可以任意的变化。

    img

    桥接模式解决了多层继承的结构,处理多维度变化的场景,将各个维度设计成独立的继承结构。使各个维度可以独立的扩展在抽象层建立联系。

    package com.dyleaf.structure.BridgePattern;
    
    public interface ImplementorBrand {
        public void sale();
    }
    class  ConcreteImplementorAcer implements ImplementorBrand{
    
        @Override
        public void sale() {
            System.out.println("宏碁品牌");
        }
    }
    
    class ConcreteImplementorApple implements ImplementorBrand{
        @Override
        public void sale() {
            System.out.println("苹果品牌");
        }
    }
    
    class ConcreteImplementorDell implements ImplementorBrand{
        @Override
        public void sale() {
            System.out.println("戴尔品牌");
        }
    }
    
    package com.dyleaf.structure.BridgePattern;
    
    public class AbstractionComputer {
        protected ImplementorBrand brand;
    
        public AbstractionComputer(ImplementorBrand brand){
            this.brand=brand;
        }
    
        public void sale(){
            brand.sale();
        }
    }
    
    /**
     * 扩展部分
     */
    class RefinedAbstractionDesktop extends AbstractionComputer{
        public RefinedAbstractionDesktop(ImplementorBrand brand) {
            super(brand);
        }
    
        @Override
        public void sale() {
            //添加自己的特性,实际业务。
            paly();
            super.sale();
        }
    
        public void paly(){
            System.out.println("我台式机抗摔打");
        }
    }
    
    class RefinedAbstractionLaptop extends AbstractionComputer{
        public RefinedAbstractionLaptop(ImplementorBrand brand) {
            super(brand);
        }
    
        @Override
        public void sale() {
            //添加自己的特性,实际业务。
            lighting();
            super.sale();
        }
    
        public void lighting(){
            System.out.println("我笔记本电脑充电5分钟,续航5小时");
        }
    }
    
    class RefinedAbstractionPad extends AbstractionComputer{
        public RefinedAbstractionPad(ImplementorBrand brand) {
            super(brand);
        }
    
        @Override
        public void sale() {
            //添加自己的特性,实际业务。
            weighting();
            super.sale();
        }
    
        public void weighting(){
            System.out.println("我平板电脑便于携带");
        }
    }
    

    优缺点

    • 不同对象间的组合产生不同的结果,将抽象和实现进行分离,当然,如果要扩展功能的,只要实现相应的接口,继承对应的类。就可以。
    • 把抽象(abstraction)与行为实现(implementation)分离开来,从而可以保持各部分的独立性以及应对它们的功能扩展

    see source code

  • 相关阅读:
    Java之五种遍历Map集合的方式
    CUDA功能和通用功能
    编写CUDA内核
    LLD-LLVM链接器
    Pass Infrastructure基础架构(下)
    Pass Infrastructure基础架构(上)
    算子规范化
    多级中间表示概述MLIR
    “ compiler-rt”运行时runtime库
    LLDB调试器
  • 原文地址:https://www.cnblogs.com/Dyleaf/p/8507040.html
Copyright © 2020-2023  润新知