美文网首页
iOS 设计模式的应用 ⑦ 桥接模式

iOS 设计模式的应用 ⑦ 桥接模式

作者: _涼城 | 来源:发表于2022-05-10 07:13 被阅读0次

    前言

        比方说有一家电视机制造商,他们生产的每台电视机都带有一个遥控器,用户可以用遥控器进行切换频道之类的操作。这里遥控器就是电视机的接口。如果每个电视机型号需要一个专用的遥控器,那么单是遥控器就会导致设计激增。我们可以把遥控器逻辑同实际的电视机型号分离开来,这样电视机型号的改变就不会对遥控器的设计有任何影响。遥控器的同一个设计可以被复用和扩展,而不会影响其他电视机型号。 在面向对象的软件设计中也有类似的情形,从针对不同的实现中,分离出其可被复用的抽象称为桥接模式

    什么是桥接模式

        桥接(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化。这种模式涉及到一个作为桥接的接口,使得抽象层次结构从其实现中分离出来,抽象层定义了供客户端使用的上层的抽象接口,实现层次则定义了供抽象层次使用的底层接口,实现类的引用被封装与抽象层的实例中时,桥接就形成了。这两种类型的类可被结构化改变而互不影响。

    桥接模式的类图.png

        Abstraction 是定义了供客户端使用的上层抽象接口的父接口。它有一个对 Implementor 实例的引用,Implementor 定义了实现类的接口。这个接口不必跟 Abstraction 的接口一致。Implementor 的接口提供基本操作,而 Abstraction 的上层操作基于这些基本操作。当客户端向 Abstraction 的实例发送 operation 消息时,这个方法向 imp 发送 operationImp 消息。实际的 ConcreteImplementator 将作出响应并接收任务。

    什么时候使用桥接模式

    • 不想在抽象与其实现之间形成固定的绑定关系
    • 抽象及其实现都应可以通过子类独立化进行扩展
    • 对抽象的实现进行修改不应影响客户端代码
    • 如果每个实现需要额外的子类以细化抽象,则说明有必要把它们分成两个部分
    • 想在带有不同抽象接口的多个对象之前共享一个实现。

    实现系统可能有多个角度分类,每一种角度都可能变化。在有多种可能会变化的情况下,用继承会扩展起来不灵活。

    桥接模式的优缺点

    桥接模式的优点

    1. 抽象和实现的分离。
    2. 优秀的扩展能力。
    3. 实现细节对客户透明。

    桥接模式的缺点

        桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。

    桥接模式的实现

        以虚拟操作手柄为例,虚拟控制器接收了用户的输入动作,涉及上、下、左、右、选中、开始、按键 A 和 B,而仿真器则负责对命令进行处理底层事件,两个层次结构都有不同的接口,但是通过对象组合的关系,在两个层次接口的上层之前形成桥接,从而联系起来。

        定义用户输入动作命令类型

    typedef enum
    {
      kConsoleCommandUp,
      kConsoleCommandDown,
      kConsoleCommandLeft,
      kConsoleCommandRight,
      kConsoleCommandSelect,
      kConsoleCommandStart,
      kConsoleCommandAction1,
      kConsoleCommandAction2
    } ConsoleCommand;
    
    

        定义一个仿真器 <ConsoleEmulator> 协议,处理底层指令,并定义实体类遵守 <ConsoleEmulator> 协议。

    @protocol ConsoleEmulator <NSObject>
    - (void) loadInstructionsForCommand:(ConsoleCommand) command;
    - (void) executeInstructions
    @end
    @interface GameBoyEmulator : NSObject <ConsoleEmulator> 
    {
    
    }
    
    // overridden behaviors from the abstract class
    - (void) loadInstructionsForCommand:(ConsoleCommand) command;
    - (void) executeInstructions;
    
    // other behaviors and properties.
    @end
    @implementation GameBoyEmulator
    
    - (void) loadInstructionsForCommand:(ConsoleCommand) command
    {
        NSLog(@"load specific instructions for  the Game Boy");
        //
    }
    
    - (void) executeInstructions
    {
        NSLog(@"execute loaded instructions ");
        // execute loaded instructions
    }
    
    @end
    @interface GameGearEmulator : NSObject <ConsoleEmulator> 
    {
    
    }
    
    // overridden behaviors from the abstract class
    - (void) loadInstructionsForCommand:(ConsoleCommand) command;
    - (void) executeInstructions;
    
    // other behaviors and properties.
    
    @end
    @implementation GameGearEmulator
    
    - (void) loadInstructionsForCommand:(ConsoleCommand) command
    {
        // load specific instructions for
        // the Game Gear
      NSLog(@"load specific instructions for  the Game Gear");
    }
    
    - (void) executeInstructions
    {
        // execute loaded instructions
      NSLog(@"execute loaded instructions ");
    }
    
    @end
    
    

        定义一个 ConsoleController 控制器抽象类,其与遵守 ConsoleEmulator协议的实体类建立联系。

    @interface ConsoleController : NSObject 
    @property (nonatomic, strong) id <ConsoleEmulator> emulator;
    - (void) setCommand:(ConsoleCommand) command;
    @end
    @implementation ConsoleController
    - (void) setCommand:(ConsoleCommand) command
    {
      [_emulator loadInstructionsForCommand:command];
      [_emulator_ executeInstructions];
    }
    
    @end
    
    

        定义 TouchConsoleController 继承 ConsoleController。实现接收用户的动作,并调用父类的 - (void) setCommand:(ConsoleCommand) command; 方法。

    @interface TouchConsoleController : ConsoleController 
    {
    
    }
    
    - (void) up;
    - (void) down;
    - (void) left;
    - (void) right;
    - (void) select;
    - (void) start;
    - (void) actionA;
    - (void) actionB;
    
    @end
    @implementation TouchConsoleController
    
    - (void) up
    {
      [super setCommand:kConsoleCommandUp];
    }
    
    - (void) down
    {
      [super setCommand:kConsoleCommandDown];
    }
    
    - (void) left
    {
      [super setCommand:kConsoleCommandLeft];
    }
    
    - (void) right
    {
      [super setCommand:kConsoleCommandRight];
    }
    
    - (void) select
    {
      [super setCommand:kConsoleCommandSelect];
    }
    
    - (void) start
    {
      [super setCommand:kConsoleCommandStart];
    }
    
    - (void) actionA
    {
      [super setCommand:kConsoleCommandAction1];
    }
    
    - (void) actionB
    {
      [super setCommand:kConsoleCommandAction2];
    }
    
    @end
    

    总结

        当程序逐渐变大变复杂时,会有越来越多小型的类从设计和应用模式中演化出来。如果没有一种简化的方式来使用这些类,客户端代码最终将变得越来越大、越来越难以理解,而且,维护会繁琐无趣。外观有助于提供一种更为简洁的方式来使用子系统中的这些类,处理这些子系统类的默认行为的,可能只是定义在外观中的一个简单的方法,而不必直接去使用这些类。

    相关文章

      网友评论

          本文标题:iOS 设计模式的应用 ⑦ 桥接模式

          本文链接:https://www.haomeiwen.com/subject/fxzkurtx.html