Bridge 桥接模式(结构型模式)

抽象与实现

抽象不应该依赖于实现细节,实现细节应该依赖于抽象。

抽象B稳定,实现细节b变化

问题在于如果抽象B由于固有的原因,本身并不稳定,也有可能变化,怎么办?

举例来说

  假如我们需要开发一个同时支持PC和手机的坦克游戏,游戏在PC和手机上功能都一样,都有同样的类型,面临同样的需求变化,比如坦克可能有多种不同的型号:T50,T75,T90……

对于其中坦克设计,我们可能很容易设计出来一个Tank的抽象基类:

    /// <summary>
/// 抽象Tank
/// </summary>
public abstract class Tank
{
public abstract void Shot();
public abstract void Run();
public abstract void Turn();
} //各种实现
public class T50 : Tank
{
//……
}
public class T75 : Tank
{
//……
}
public class T90 : Tank
{
//……
}

另外的变化原因

但是PC和手机上的图形绘制、生效、操作等实现完全不同……因此对于各种型号的坦克,都要提供各种不同平台上的坦克的实现:

    //PC平台实现
public class PCT50 : T50
{
//……
}
public class PCT75 : T75
{
//……
}
public class PCT90 : T90
{
//……
}
//手机平台实现
public class MobileT50 : T50
{
//……
}
public class MobileT75 : T75
{
//……
}
public class MobileT90 : T90
{
//……
}

这样的设计会带来很多问题:有很多重复代码,类的结构过于复杂,难以维护,最致命的是引入任何新平台,比如在TV上的Tank游戏,都会让整个类层级结构复杂变化。

动机(Motivation)

思考上述问题的症结:事实上由于Tank类型的固有逻辑,使得Tank类型具有了两个变化的维度——一个变化的维度为“平台的变化”,一个变化的维度为“型号的变化”。

如何应对这种“多维度的变化”?如何利用面向对象技术使得Tank类型可以轻松地沿着“平台”和“型号”两个方向变化,而不引入额外的复杂度?

意图(Intent)

将抽象部分与现实部分分离,使它们可以独立地变化。——《设计模式》GoF

代码示例:

    //平台
public abstract class TankPlatformImplementation
{
public abstract void MoveTankTo(Point to);
public abstract void DrawTank();
public abstract void DoShot();
}
//PC平台
public class PCTankImplementation : TankPlatformImplementation
{
public override void MoveTankTo(Point to)
{
//……
} public override void DrawTank()
{
//……
} public override void DoShot()
{
//……
}
}
//手机平台
public class MobileTankImplementation : TankPlatformImplementation
{
public override void MoveTankTo(Point to)
{
//……
} public override void DrawTank()
{
//……
} public override void DoShot()
{
//……
}
}
    /// <summary>
/// 抽象Tank
/// </summary>
public abstract class Tank
{
protected TankPlatformImplementation tankImpl; public Tank(TankPlatformImplementation tankImpl)
{
this.tankImpl = tankImpl;
} public TankPlatformImplementation TankImpl
{
get { return this.tankImpl; }
set { this.tankImpl = tankImpl; }
}
public abstract void Shot();
public abstract void Run();
public abstract void Turn();
}
    //各种实现
public class T50 : Tank
{
public T50(TankPlatformImplementation tankImpl):base(tankImpl)
{ }
public override void Shot()
{
//……
} public override void Run()
{
//……
} public override void Turn()
{
//……
}
}
public class T75 : Tank
{
public T75(TankPlatformImplementation tankImpl):base(tankImpl)
{ }
public override void Shot()
{
//……
} public override void Run()
{
//……
} public override void Turn()
{
//……
}
}
public class T90 : Tank
{
public T90(TankPlatformImplementation tankImpl):base(tankImpl)
{ }
public override void Shot()
{
//……
} public override void Run()
{
//……
} public override void Turn()
{
//……
}
}
    //调用
public class App
{
public static void Main()
{
TankPlatformImplementation tankImpl=new MobileTankImplementation();//手机平台调用
T50 tankT50=new T50(tankImpl);
}
}

将一个事物中多个维度的变化分离,使它们可以独立地变化

Bridge模式的几个要点

Bridge模式使用“对象间的组合关系”解耦了抽象和现实之间固有的绑定关系,使得抽象(Tank的型号)和实现(不同的平台)可以沿着各自的维度来变化。

所谓抽象和实现可以沿着各自维度变化,即“子类化”它们,比如Tank型号子类,和不同的平台子类。得到各个子类之后,便可以任意组合它们,从而获得不同平台的不同型号。

Bridge模式有时候类似于多继承方案,但是多继承方案往往违背单一职责原则(即一个类只有一个变化的原因),复用性比较差。Bridge模式是比多继承方案更好的解决办法。

Bridge模式的应用一般在“两个非常强的变化维度”,有时候即使有两个变化的维度,但是某个方向的变化维度并不剧烈——换言之两个变化不会导致纵横交错的结果,并不一定要使用Bridge模式。

设计模式07: Bridge 桥接模式(结构型模式)的更多相关文章

  1. .NET设计模式(15):结构型模式专题总结(转)

    摘要:结构型模式,顾名思义讨论的是类和对象的结构,它采用继承机制来组合接口或实现(类结构型模式),或者通过组合一些对象,从而实现新的功能(对象结构型模式).这些结构型模式,它们在某些方面具有很大的相似 ...

  2. 设计模式(十二): Flyweight享元模式 -- 结构型模式

    说明: 相对于其它模式,Flyweight模式在PHP实现似乎没有太大的意义,因为PHP的生命周期就在一个请求,请求执行完了,php占用的资源都被释放.我们只是为了学习而简单做了介绍. 1. 概述 面 ...

  3. 代理模式/proxy模式/结构型模式

    代理模式proxy 定义 为其他对象提供一种代理,并以控制对这个对象的访问.最简单的理解,买东西都是要去商店的,不会去工厂. java实现三要素 proxy(代理)+subject(接口)+realS ...

  4. Bridge桥接模式(结构型模式)

    现有一个需求,一个游戏系统需要构建不同风格的房屋,暂不考虑其他设计模式,需要能实现在PC端.移动端....等等多个平台的构建.最简单的实现方式如下: /// <summary> /// 房 ...

  5. 设计模式(十三): Proxy代理模式 -- 结构型模式

      设计模式(十一)代理模式Proxy(结构型) 1.概述 因为某个对象消耗太多资源,而且你的代码并不是每个逻辑路径都需要此对象, 你曾有过延迟创建对象的想法吗 ( if和else就是不同的两条逻辑路 ...

  6. 设计模式学习之路——Facade 外观模式(结构型模式)

    动机: 组件的客户和组件中各种复杂的子系统有了过多的耦合,随着外部客户程序和各子系统的演化,这种过多的耦合面临很多变化的挑战.如何简化外部客户程序和系统间的交互接口?如何将外部客户程序的演化和内部子系 ...

  7. 设计模式(十):Decorator装饰者模式 -- 结构型模式

    1. 概述 若你从事过面向对象开发,实现给一个类或对象增加行为,使用继承机制,这是所有面向对象语言的一个基本特性.如果已经存在的一个类缺少某些方法,或者须要给方法添加更多的功能(魅力),你也许会仅仅继 ...

  8. 设计模式(十一):FACADE外观模式 -- 结构型模式

    1. 概述 外观模式,我们通过外观的包装,使应用程序只能看到外观对象,而不会看到具体的细节对象,这样无疑会降低应用程序的复杂度,并且提高了程序的可维护性.例子1:一个电源总开关可以控制四盏灯.一个风扇 ...

  9. 设计模式(八):Bridge桥接模式 -- 结构型模式

    1. 概述 在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种“多维度的变化”?如何利用面向对象的技术来使得该类型能够轻松的沿着多个方向进行变化,而又不引入额外的复杂度 ...

  10. 设计模式(九):Composite组合模式 -- 结构型模式

    1. 概述 在数据结构里面,树结构是很重要,我们可以把树的结构应用到设计模式里面. 例子1:就是多级树形菜单. 例子2:文件和文件夹目录 2.问题 我们可以使用简单的对象组合成复杂的对象,而这个复杂对 ...

随机推荐

  1. 【转】java接口的性能测试

    这周尝试了一把性能测试,之前都是测试网站的性能测试,java接口的性能测试还是头一次,学到了很多,特此分享一下. 主要用到了两个性能测试工具,一个是jmeter,一个是LoadRunner. 使用jm ...

  2. php对数组中的值进行排序

    案例 <?php $a = array('1124','1125','1126'); $s1 = 1124; $s2 = 1125; $ks1 = array_search($s1,$a); $ ...

  3. C#三层架构实例

    对于三层的概念查也查了,看也看了,下面是我找的一个关于三层的简单实例,真正看一下它是如何具体实现的. 我们先来一起看看 实体类-Model 实质:实体类就是在完成数据库与实体类对应的功能,一个类是一张 ...

  4. 1.solr学习速成之配置文件

    什么是solr Solr是一个独立的企业级搜索应用服务器,它对外提供类似于Web-service的API接口.用户可以通过http请求,向搜索引擎服务器提交一定格式的XML文件,生成索引:也可以通过H ...

  5. Full Binary Tree(sdut 2882)

    Problem Description: In computer science, a binary tree is a tree data structure in which each node ...

  6. const的作用

    const的作用 const是C语言的一种关键字,起受保护,防止以外的变动的作用!可以修饰变量,参数,返回值,甚至函数体.const可以提高程序的健壮性,你只管用到你想用的任何地方. (一)const ...

  7. android 拍照+拍照button 以及返回按钮布局

    公司最近做一个项目拍照总是崩溃,所以决定自己写一个拍照的方法,在网上调研一番,写了一个简单demo,现共享如下 主要CameraActivity CameraActivity package com. ...

  8. Resin 的watchdog(看门狗)介绍和resin负载均衡实现

    为了稳定和安全,Resin使用一个独立的watchdog进程来启动和监视Resin服务器.watchdog连续你检测Resin服务器的状态,如果其没有反应或者迟钝,将会重启Resin服务器进程.大多数 ...

  9. mysql中如何不重复插入满足某些条件的重复的记录的问题

    最近在项目中遇到了这样的一个问题“: 在mysql数据库中需要每次插入的时候不能插入三个字段都相同的记录.在这里使用到了 insert into if not exists  和insert igno ...

  10. mysql外键约束总结

    总结三种MySQL外键约束方式 如果表A的主关键字是表B中的字段,则该字段称为表B的外键,表A称为主表,表B称为从表.外键是用来实现参照完整性的,不同的外键约束方式将可以使两张表紧密的结合起来,特别是 ...