• 桥接模式及C++实现


    桥接模式

    先说说桥接模式的定义:将抽象化(Abstraction)与实现化(Implementation)分离,使得二者可以独立地变化。

    桥接模式号称设计模式中最难理解的模式之一,关键就是这个抽象和实现的分离非常让人奇怪,大部分人刚看到这个定义的时候都会认为实现就是继承自抽象,那怎么可能将他们分离呢。

    这里引用《大话设计模式》里面的那个例子。这个例子中,每次添加一个新的手机品牌,则必须要添加相应的通讯录和游戏,而每次要给每个手机添加新功能,则所有的手机品牌下都必须继承一个新的类,这样工作量就大了,而且可能通讯录和游戏的实现方法是一样的,这就有很多重复代码。看到这里可能已经看到了端倪了,虽然这个最顶层的抽象手机品牌一般是固定不变的,但是下面的各个继承类手机品牌M和手机品牌N却是时常会发生变化的。而只要手机品牌M和手机品牌N发生变化,它下面的继承类也要发生变化,这样极大的增加了代码的耦合性,加入通讯录和游戏下面还继续继承有类的话,那耦合性就更强了,改起来基本就是噩梦了。

    其实也可以这样看,虽然手机品牌M和手机品牌N这两个类是有一部分抽象,但是还没有达到完全的抽象,还是会发生变化的。

    所以,其实定义里说的实现是指的最下层的那些具体实现,抽象是指的他的父类或者更上层的父类,而要将抽象和实现分离,就是分离这个抽象和实现。说的通俗点,就是不要继承的太多了,最好是就继承一层。(我自己的理解)所以才有了合成/聚合复用原则。

    合成/聚合复用原则:尽量使用合成/聚合,尽量不要使用类继承。我对这句话的理解就是,不要继承太多了,如果需要太多继承,可以考虑改为合成/聚合。

    image

    下面可以看看桥接模式的具体类图了。桥接模式就将实现与抽象分离开来,使得RefinedAbstraction依赖于抽象的实现,这样实现了依赖倒转原则,而不管左边的抽象如何变化,只要实现方法不变,右边的具体实现就不需要修改,而右边的具体实现方法发生变化,只要接口不变,左边的抽象也不需要修改。

    说起来,其实桥接模式倒是与抽象工厂模式有点像,可以回忆一下抽象工厂模式,抽象工厂模式也是解决多种因素变化的一种方式,抽象工厂模式中,产品的种类和产品的具体实现都会发生变化,于是将产品的种类抽象出来,将具体的实现隔离开来。

    image

    最新体会:有一种情况,你事先定义了Abstction类和RefinedAbstraction类,你的代码中直接使用的是RefinedAbstraction类,刚开始RefinedAbstraction是够用的。但后来你希望operation()能在不同的情况下有不同的实现,这时候原有的结构就不够用了,你不可能重新继承一个类,那样所有的地方都必须修改,可以考虑的做法就是继承RefinedAbstraction类,这样的改动就比较少,但这样不是最好的。最好的应该是使用上面的桥接模式,将实现分离出来,这样所有的地方都不需要修改,只要添加它的实现就可以了。

    常用的场景

    1.当一个对象有多个变化因素的时候,考虑依赖于抽象的实现,而不是具体的实现。如上面例子中手机品牌有2种变化因素,一个是品牌,一个是功能。

    2.当多个变化因素在多个对象间共享时,考虑将这部分变化的部分抽象出来再聚合/合成进来,如上面例子中的通讯录和游戏,其实是可以共享的。

    3.当我们考虑一个对象的多个变化因素可以动态变化的时候,考虑使用桥接模式,如上面例子中的手机品牌是变化的,手机的功能也是变化的,所以将他们分离出来,独立的变化。

    优点

    1.将实现抽离出来,再实现抽象,使得对象的具体实现依赖于抽象,满足了依赖倒转原则。

    2.将可以共享的变化部分,抽离出来,减少了代码的重复信息。

    3.对象的具体实现可以更加灵活,可以满足多个因素变化的要求。

    缺点

    1.客户必须知道选择哪一种类型的实现。

    C++实现代码

     1 #ifndef _ABSTRACTION_H_
     2 #define _ABSTRACTION_H_
     3 
     4 #include "AbstractionImplement.h"
     5 
     6 class Abstraction
     7 {
     8 public:
     9     Abstraction();
    10     virtual ~Abstraction();
    11 
    12     virtual void operation() = 0;
    13 
    14 
    15 };
    16 
    17 class DefinedAbstraction: public Abstraction
    18 {
    19 public:
    20     DefinedAbstraction(AbstractionImplement* absImp);
    21     ~DefinedAbstraction();
    22 
    23     void operation();
    24 
    25 private:
    26     AbstractionImplement* absImp;
    27 };
    28 
    29 
    30 #endif
     1 #include "Abstraction.h"
     2 
     3 
     4 Abstraction::Abstraction()
     5 {
     6 
     7 }
     8 
     9 
    10 
    11 Abstraction::~Abstraction()
    12 {
    13 
    14 }
    15 
    16 
    17 DefinedAbstraction::DefinedAbstraction(AbstractionImplement* absImp)
    18 {
    19     this->absImp = absImp;
    20 }
    21 
    22 
    23 DefinedAbstraction::~DefinedAbstraction()
    24 {
    25 
    26 }
    27 
    28 
    29 void DefinedAbstraction::operation()
    30 {
    31     absImp->operation();
    32 }
     1 #ifndef _ABSTRACTIONIMPLEMENT_H_
     2 #define _ABSTRACTIONIMPLEMENT_H_
     3 
     4 
     5 class AbstractionImplement
     6 {
     7 public:
     8     AbstractionImplement();
     9     virtual ~AbstractionImplement();
    10 
    11     virtual void operation() = 0;
    12 };
    13 
    14 
    15 class ConcreteAbstractionImplement1:public AbstractionImplement
    16 {
    17 public:
    18     ConcreteAbstractionImplement1();
    19     ~ConcreteAbstractionImplement1();
    20 
    21     void operation();
    22 };
    23 
    24 class ConcreteAbstractionImplement2:public AbstractionImplement
    25 {
    26 public:
    27     ConcreteAbstractionImplement2();
    28     ~ConcreteAbstractionImplement2();
    29 
    30     void operation();
    31 };
    32 
    33 
    34 #endif
     1 #include "AbstractionImplement.h"
     2 #include <stdio.h>
     3 
     4 
     5 
     6 AbstractionImplement::AbstractionImplement()
     7 {
     8 
     9 }
    10 
    11 
    12 AbstractionImplement::~AbstractionImplement()
    13 {
    14 
    15 }
    16 
    17 
    18 ConcreteAbstractionImplement1::ConcreteAbstractionImplement1()
    19 {
    20 
    21 }
    22 
    23 
    24 ConcreteAbstractionImplement1::~ConcreteAbstractionImplement1()
    25 {
    26 
    27 }
    28 
    29 
    30 void ConcreteAbstractionImplement1::operation()
    31 {
    32     fprintf(stderr, "ConcreteAbstractionImplement1
    " );
    33 }
    34 
    35 
    36 ConcreteAbstractionImplement2::ConcreteAbstractionImplement2()
    37 {
    38 
    39 }
    40 
    41 
    42 ConcreteAbstractionImplement2::~ConcreteAbstractionImplement2()
    43 {
    44 
    45 }
    46 
    47 
    48 void ConcreteAbstractionImplement2::operation()
    49 {
    50     fprintf(stderr, "ConcreteAbstractionImplement2
    " );
    51 }
     1 #include "Abstraction.h"
     2 
     3 
     4 
     5 int main()
     6 {
     7     AbstractionImplement* absImp1 = new ConcreteAbstractionImplement1();
     8     Abstraction* abs1 = new DefinedAbstraction(absImp1);
     9 
    10     abs1->operation();
    11 
    12     AbstractionImplement* absImp2 = new ConcreteAbstractionImplement2();
    13     Abstraction* abs2 = new DefinedAbstraction(absImp2);
    14 
    15     abs2->operation();    
    16     return 0;
    17 }
    1 g++ -o client client.cpp Abstraction.cpp AbstractionImplement.cpp

    运行结果

    image

  • 相关阅读:
    day 1 python全栈学习笔记(不完全版)
    python全栈学习之旅正式开始了!
    [Web] Web开发中你可以借鉴的东西
    Google Guice 系列教程 - 基础实践
    Ant
    [Android]Android高级UI开发系列教程(一) Android拖拽教程
    [Android]Android高级UI开发系列教程(二) Android绘制教程
    [Android] 布局基础知识点
    BitbucketGit
    [Android]Android高级UI开发系列教程(三) Android样式和主题教程
  • 原文地址:https://www.cnblogs.com/cxjchen/p/3156872.html
Copyright © 2020-2023  润新知