设计模式之Birdge(桥接)模式
1、出现原因
1、同一个类型,有两个变化的维度(两个维度的抽象:一个抽象部分的抽象,一个实现部分的抽象)
2、如何应对这种“多维度的变化”?如何利用面向对象技术来使得同一类型可以轻松地沿着两个方向变化,而不引入额外的复杂度?
2、具体的例子
数据库操作
操作类型:增删改查 (具体功能的实现部分)
操作对象:客户,订单,产品…(对应上面的增删改查是 1对多的关系(通过聚合关系联系起来))
手机软件
软件功能:通讯录,游戏
支持品牌:M(摩托骡拉),N(喏鸡呀)
计算机软件
软件功能:游戏,开发工具,绘图软件…
运行平台:Windows,Unix….
过度的使用继承:
——以手机软件为例:
以手机品牌分类:
以手机软件分类:
我们仔细观察,如果给上面的增加一个手机软件,,那么每个手机品牌都要增加这个手机软件,都要变化,耦合度太高了。
使用桥接模式重构上面的:
3、意图:
将抽象部分与实现部分分离,使它们都可以独立地变化。
4、结构图:
5、代码演示
//桥接模式:两个维度的变化(一个是抽象,一个是实现),并且 这两个维度 是一对多的(抽象 1对多 实现)/聚合 关系;通过桥接模式将 两个维度(抽象和实现) 隔离。将 两个维度的变化 封装起来,不管一个维度 怎么 变化 都不会影响另一个维度的 变化。。所以 耦合度 降低了 很多(相比以前的 继承关系) //第一个维度(实现部分)
public interface IPhoneSoftware
{
void Start();
} //第二个维度(抽象部分) public abstract class PhoneBrand
{
private List<IPhoneSoftware> phoneSoftwares = new List<IPhoneSoftware>(); public void Instance(IPhoneSoftware software)
{
phoneSoftwares.Add(software);
} public void StareAllSoftware()
{
if (phoneSoftwares.Count <= )
{
throw new Exception("没有可以执行的手机软件!");
}
else
{
foreach (var item in phoneSoftwares)
{
item.Start();
}
}
}
} //第一个维度(实现部分:实现的功能)
public class KuGou : IPhoneSoftware
{
public void Start()
{
Console.WriteLine("酷狗音乐已经开启,可以欣赏音乐了!");
}
} public class QQ : IPhoneSoftware
{
public void Start()
{
Console.WriteLine(" QQ已经开启了,可以进行聊天了!");
}
} //第二个维度(抽象部分的具体的)
public class Samsung : PhoneBrand
{ } public class Iphone : PhoneBrand
{
}
Birdge模式
客户端代码:
//创建抽象
PhoneBrand samsung = new Samsung();
//创建实现
IPhoneSoftware soft1 = new QQ();
IPhoneSoftware soft2 = new KuGou();
//将抽象和实现相结合
samsung.Instance(soft1);
samsung.Instance(soft2); samsung.StareAllSoftware();
6、实现要点
1、Abstraction(抽象部分):定义抽象类的接口;;并维护指向Implementor类(实现部分)的对象指针。(抽象部分变化不会影响到实现部分,实现部分变化不会影响到抽象部分,因为他们是通过 聚合关系 连接起来的,扩展只是对他们各自的抽象 进行扩展变化)
2、Implementor:定义实现类的接口,该接口不一定要与Abstraction的接口完全一致。事实上这两个接口可以完全不同。(因为是对 各自方面的抽象(是两个不同的维度),通过 聚合关系 联系起来)
3、一般而言,Implementor接口仅提供基本操作(实现部分的具体功能),而Abstraction(是对 具体实现的 调用)则定义了基于操作的较高层次的操作。
7、效果
1、将接口(抽象)与实现分离:一个接口可以有若干实现(聚合关系),一个实现也可以为若干对象服务(一个实现的部分的具体功能 可以进行 复用,,可以多个对象(抽象下面具体的 扩展的抽象)里面进行使用),表示逻辑的对象可以动态地与实现功能的对象组合。
2、提高可扩充性:逻辑和实现都可以通过类层次的扩展进行扩充。
3、逻辑和实现被封装在不同的对象中,逻辑对实现的引用是动态进行的。在实际中,需要分别用不同的“工厂”创建逻辑和实现,然后组装。
8、适用性
1、不希望在业务(抽象部分)和业务的软件(实现部分)实现之间存在固定的绑定关系。例如,不希望“入库”业务过程和具体的数据库访问技术或数据库管理系统有过于密切的关系。
2、希望类的抽象和实现部分可以扩充,进而实现不同的抽象接口和实现部分的组合。(实现部分可以在不同的抽象部分 可以被复用)
修改实现部分对用户不产生影响,即代码无须重新编译。(因为用户操作的是实现的接口,具体的实现接口下面的实现部分已经封装起来了)
3、复用实现部分。由于实现部分所处的层次较低,因此可以被多种业务模块复用。例如,数据库访问模块可以用在多种业务单元中。
9、总结
1、Bridge模式使用“对象间的组合关系”解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着各自的维度来变化。
2、所谓抽象和实现沿着各自维度的变化,即“子类化”它们。得到各个子类之后,便可以任意组合它们。
3、Bridge模式有时候类似于多继承方案,但是多继承方案往往违背单一职责原则(即一个类只有一个变化的原因),复用性比较差。Bridge模式是比多继承方案更好的解决方法。
4、Bridge模式的应用一般在“两个非常强的变化维度”(含有两个方向可以进行派生),有时候即使有两个变化的维度,但是某个方向的变化维度并不剧烈——换言之两个变化不会导致纵横交错的结果,并不一定要使用Bridge模式(设计模式是一种思想,并不一定要硬套)。
设计模式之Birdge(桥接)模式的更多相关文章
- Java设计模式之《桥接模式》及应用场景
摘要: 原创作品,可以转载,但是请标注出处地址http://www.cnblogs.com/V1haoge/p/6497919.html 这里摘抄一份他处的概念,你可以不必理会,先看下面得讲解与实例, ...
- 实例解析Python设计模式编程之桥接模式的运用
实例解析Python设计模式编程之桥接模式的运用 这篇文章主要介绍了Python设计模式编程之桥接模式的运用,桥接模式主张把抽象部分与它的实现部分分离,需要的朋友可以参考下 我们先来看一个例子: #e ...
- java23种设计模式——七、桥接模式
原文地址:https://www.cnblogs.com/chenssy/p/3317866.html 源码在我的github和gitee中获取 目录 java23种设计模式-- 一.设计模式介绍 j ...
- Net设计模式实例之桥接模式( Bridge Pattern)
一.桥接模式简介(Brief Introduction) 桥接模式(Bridge Pattern),将抽象部分与它的实现部分分离,使的抽象和实现都可以独立地变化. Decouple an abstra ...
- [设计模式] javascript 之 桥接模式
桥接模式说明 定义:分离抽象化与实现化,使之可以自由独立的变化: 说明:由于软件环境需求原因,使得类型抽象具有多种实现以自身变化定义等情况,这使得我们要分离抽象实现与具体实现,使得抽象化与实现化解耦, ...
- 设计模式学习之桥接模式(Bridge,结构型模式)(15)
参考地址:http://terrylee.cnblogs.com/archive/2006/02/24/336652.html 概述 在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化, ...
- 【读书笔记】读《JavaScript设计模式》之桥接模式
桥接模式(Bridge)将抽象部分与它的实现部分分离,使它们都可以独立地变化. 一.使用场景 使用场景一:事件监控 对于前端而言,最典型的使用场景——事件监控.如—— addEvent(element ...
- Java设计模式系列之桥接模式
桥接模式(Bridge)的定义 在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种“多维度的变化”?这就要使用桥接模式 将抽象部分与它的实现部分分离,使它们都可以独立地 ...
- java设计模式-----14、桥接模式
Bridge 模式又叫做桥接模式,是构造型的设计模式之一.Bridge模式基于类的最小设计原则,通过使用封装,聚合以及继承等行为来让不同的类承担不同的责任.它的主要特点是把抽象(abstraction ...
- 设计模式学习心得<桥接模式 Bridge>
说真的在此之前,几乎没有对于桥接模式的应用场景概念. 桥接(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化.这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来 ...
随机推荐
- PDM文件编辑
需要把Oracle中的表,导出到已有的PDM文件中. 1.Oracle导出表脚本 1) 2) 3) 2.PowerDesigner导入脚本 1) 2) 3) 4)
- final 的用法总结
1.修饰成员变量 修饰普通变量 表明这个变量是一个常量,不可以修改这个变量的值,一般这样的变量的变量名都要大写 修饰引用变量 表明这个引用不能够指向别的对象了,只能够指向指定的这个对象 2.修饰方法 ...
- Web.config配置文件
优点:Web.config配置文件使得ASP.NET应用程序的配置变得灵活高效和容易实现并为ASP.NET应用提供了可扩展的配置,使得应用程序能够自定义配置,同时还包括的优点有:配置设置易读性.更新的 ...
- minicom/kermit捕捉日志
1.minicom捕捉日志 ctrl-A Z 命令窗口中有 Capture on/off......L 2.kermit捕捉日志 ctrl-\ C进入kermit命令行模式 log session ...
- puppet实现主从部署各种软件实战参考模型
puppet实现主从部署各种软件实战参考模型 实验要求: 1.我将准备三个节点 node2 , node3 , node4 2.我们想让节点node3部署ntp,nginx ;节点node ...
- crontab的使用说明
网上瞎转载的,仅供参考 名称 : crontab 使用权限 : 所有使用者 使用方式 : crontab file [-u user]-用指定的文件替代目前的crontab. crontab-[-u ...
- Windows Server 2008 R2 密码破解
Win 2008 Server 忘记密码怎么办,不能像Win7/8/XP 那样用PE破解就只有这种方法了1.首先,把Windows 2008 的镜像放进去光驱我们用光驱启动 2. 这时候按下S ...
- C#关于Sort排序问题
1.在集合中用Sort对集合元素进行排序 List<,,,,}; tmp.Sort((x, y) => -x.CompareTo(y)); Console.WriteLine(tmp); ...
- 用户 'sa' 登录失败。 (Microsoft SQL Server,错误: 18456)
今天登陆数据库的时候,却忽然登陆了不了,并且提示了这样的错: 解决方法: 1.用Windows身份登录数据库 2.安全性==>登录名==>双击sa 3.重设密码 4.状态==>登录: ...
- C#获取程序所在目录路径
方法1:Directory.GetCurrentDirectory().这个方法只能在.NET的完整版中使用,NETCF中不支持该功能,调用时会引发异常.获取的是当前目录,并不一定是真正的路径,跟Op ...