设计模式(7)--Bridge(桥接模式)--结构型
1.模式定义:
2.模式特点:
(1)抽象化
(2)实现化
(3)脱耦
- 桥接模式使用对象见的组合关系解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着各自的维度来变化。
- 所谓抽象和实现沿着各自维度的变化,即“子类化”它们,得到各个子类之后,便可以任意它们,从而获得不同路上的不同其次。
- 桥接模式有时候类似于多继承方案,但是多继承方案往往违背了SRP原则,复用性较差。桥接模式是比继承方案更好的解决方法。
- 桥接模式的应用一般在“两个非常强的变化维度”,有时候即使有两个变化的维度,但是某个方向的变化维度并不剧烈——换而言之两个变化不会导致纵横交错的结果,并不一定要使用桥接模式。
3.使用场景:
4.模式实现:

(1)抽象化(Abstraction)角色:
public abstract class Abstraction {
protected Implementor impl;
public Abstraction(Implementor impl){
this.impl = impl;
}
//示例方法
public void operation(){
impl.operationImpl();
}
}
(2)修正抽象化(RefinedAbstraction)角色:
public class RefinedAbstraction extends Abstraction {
public RefinedAbstraction(Implementor impl) {
super(impl);
}
//其他的操作方法
public void otherOperation(){
}
}
(3)实现化(Implementor)角色:
public abstract class Implementor {
/**
* 示例方法,实现抽象部分需要的某些具体功能
*/
public abstract void operationImpl();
}
(4)具体实现化(ConcreteImplementor)角色:
public class ConcreteImplementorA extends Implementor {
@Override
public void operationImpl() {
//具体操作
}
}
public class ConcreteImplementorB extends Implementor {
@Override
public void operationImpl() {
//具体操作
}
}
5.优缺点:
(1)桥接模式的优点
[1]实现了抽象和实现部分的分离
[2]更好的可扩展性
[3]可动态的切换实现
[4]实现细节对客户端透明,可以对用户隐藏实现细节。
(2)桥接模式的缺点
[1]]桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。
[2]桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围具有一定的局限性。
6.注意事项
7.应用实例:
(1)不使用桥接模式:

[1]消息的统一接口
public interface Message {
/**
* 发送消息
* @param message 要发送消息的内容
* @param toUser 消息的接受者
*/
public void send(String message , String toUser);
}
[2]系统内短消息示例类
public class CommonMessageSMS implements Message {
@Override
public void send(String message, String toUser) {
System.out.println("使用系统内短消息的方法,发送消息'"+message+"'给"+toUser);
}
}
[3]邮件消息示例类
public class CommonMessageEmail implements Message{
@Override
public void send(String message, String toUser) {
System.out.println("使用邮件短消息的方法,发送消息'"+message+"'给"+toUser);
}
}

[1]加急消息的接口
public interface UrgencyMessage extends Message {
/**
* 监控指定消息的处理过程
* @param messageId 被监控的消息编号
* @return 监控到的消息的处理状态
*/
public Object watch(String messageId);
}
[2]系统内加急短消息示例类
public class UrgencyMessageSMS implements UrgencyMessage {
@Override
public Object watch(String messageId) {
// 根据消息id获取消息的状态,组织成监控的数据对象,然后返回
return null;
}
@Override
public void send(String message, String toUser) {
message = "加急:" + message;
System.out.println("使用系统内短消息的方法,发送消息'"+message+"'给"+toUser);
}
}
[3]邮件加急短消息示例类
public class UrgencyMessageEmail implements UrgencyMessage {
@Override
public Object watch(String messageId) {
// 根据消息id获取消息的状态,组织成监控的数据对象,然后返回
return null;
}
@Override
public void send(String message, String toUser) {
message = "加急:" + message;
System.out.println("使用邮件短消息的方法,发送消息'"+message+"'给"+toUser);
}
}




[1]抽象消息类
public abstract class AbstractMessage {
//持有一个实现部分的对象
MessageImplementor impl;
/**
* 构造方法,传入实现部分的对象
* @param impl 实现部分的对象
*/
public AbstractMessage(MessageImplementor impl){
this.impl = impl;
}
/**
* 发送消息,委派给实现部分的方法
* @param message 要发送消息的内容
* @param toUser 消息的接受者
*/
public void sendMessage(String message , String toUser){
this.impl.send(message, toUser);
}
}
[2]普通消息类
public class CommonMessage extends AbstractMessage {
public CommonMessage(MessageImplementor impl) {
super(impl);
}
@Override
public void sendMessage(String message, String toUser) {
// 对于普通消息,直接调用父类方法,发送消息即可
super.sendMessage(message, toUser);
}
}
[3]加急消息类
public class UrgencyMessage extends AbstractMessage {
public UrgencyMessage(MessageImplementor impl) {
super(impl);
}
@Override
public void sendMessage(String message, String toUser) {
message = "加急:" + message;
super.sendMessage(message, toUser);
}
/**
* 扩展自己的新功能,监控某消息的处理状态
* @param messageId 被监控的消息编号
* @return 监控到的消息的处理状态
*/
public Object watch(String messageId) {
// 根据消息id获取消息的状态,组织成监控的数据对象,然后返回
return null;
}
}
[4]实现发送消息的统一接口
public interface MessageImplementor {
/**
* 发送消息
* @param message 要发送消息的内容
* @param toUser 消息的接受者
*/
public void send(String message , String toUser);
}
[5]系统内短消息的实现类
public class MessageSMS implements MessageImplementor {
@Override
public void send(String message, String toUser) {
System.out.println("使用系统内短消息的方法,发送消息'"+message+"'给"+toUser);
}
}
[6]邮件短消息的实现类
public class MessageEmail implements MessageImplementor {
@Override
public void send(String message, String toUser) {
System.out.println("使用邮件短消息的方法,发送消息'"+message+"'给"+toUser);
}
}
[7]客户端类
public class Client {
public static void main(String[] args) {
//创建具体的实现对象
MessageImplementor impl = new MessageSMS();
//创建普通消息对象
AbstractMessage message = new CommonMessage(impl);
message.sendMessage("加班申请速批","李总");
//将实现方式切换成邮件,再次发送
impl = new MessageEmail();
//创建加急消息对象
message = new UrgencyMessage(impl);
message.sendMessage("加班申请速批","李总");
}
}
设计模式(7)--Bridge(桥接模式)--结构型的更多相关文章
- Bridge桥接模式(结构型模式)
现有一个需求,一个游戏系统需要构建不同风格的房屋,暂不考虑其他设计模式,需要能实现在PC端.移动端....等等多个平台的构建.最简单的实现方式如下: /// <summary> /// 房 ...
- 设计模式(八):Bridge桥接模式 -- 结构型模式
1. 概述 在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种“多维度的变化”?如何利用面向对象的技术来使得该类型能够轻松的沿着多个方向进行变化,而又不引入额外的复杂度 ...
- 设计模式(12)--Proxy(代理模式)--结构型
作者QQ:1095737364 QQ群:123300273 欢迎加入! 1.模式定义: 代理模式是对象的结构模式.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. ...
- 设计模式(10)--Facade(外观模式)--结构型
作者QQ:1095737364 QQ群:123300273 欢迎加入! 1.模式定义: 外观模式提供了一个统一的接口,用来访问子系统中的一群接口.外观定义了一个高层接口,让子系统更容易使 ...
- 设计模式(9)--Composite(组合模式)--结构型
1.模式定义: 组合模式属于对象的结构模式,有时又叫做“部分——整体”模式.组合模式将对象组织到树结构中,可以用来描述整体与部分的关系.组合模式可以使客户端将单纯元素与复合元素同等看待. 2.模式特点 ...
- 设计模式07: Bridge 桥接模式(结构型模式)
Bridge 桥接模式(结构型模式) 抽象与实现 抽象不应该依赖于实现细节,实现细节应该依赖于抽象. 抽象B稳定,实现细节b变化 问题在于如果抽象B由于固有的原因,本身并不稳定,也有可能变化,怎么办? ...
- C++设计模式-Bridge桥接模式
作用:将抽象部份与它的实现部份分离,使它们都可以独立地变化. 将抽象(Abstraction)与实现(Implementation)分离,使得二者可以独立地变化. 桥接模式号称设计模式中最难理解的模式 ...
- 一天一个设计模式——Bridge桥接模式
一.概念准备 在理解桥接模式之前,先要理解面向对象程序设计中的两个概念: 类的功能层次结构:假设现在有一个类Something,这个类有一些成员属性和成员方法,但是现有的功能不能满足要求,因此我们想扩 ...
- Bridge桥接模式(设计模式11)
在没有使用桥接模式: 扩展新问题(类归属膨胀问题) 1增加性的电脑类型,要增加每个品牌下面的类 2如果要增加一个新的电脑品牌,要增加美中电脑类型的类 违背单一职责原则: · 一个类:联想笔记本,有两个 ...
随机推荐
- 使用Web页面配置ESP8266的参数
前言 使用Web页面配置ESP8266的参数相对于使用串口AT指令配置更加直观和简单.与配置路由器方式类似. 基本思路 基本思路是ESP8266工作AP模式下,作为TCP Server监听TCP Cl ...
- Redis基本数据结构总结之SET、ZSET和HASH
Redis基本数据结构总结 前言 Redis的特点在于其读写速度特别快,因为是存储在内存中的,其非常适合于处理大数据量的情况:还有一个是其不同于其他的关系型数据库,Redis是非关系型数据库,也就是我 ...
- docker~save与load的使用
回到目录 对于没有私有仓库来说,将本地镜像放到其它服务器上执行时,我们可以使用save和load方法,前者用来把镜像保存一个tar文件,后台从一个tar文件恢复成一个镜像,这个功能对于我们开发者来说还 ...
- Log4Net(一):快速入门
概览 Log4Net是Apache Log4J框架在.NET平台上的实现,它是一个帮助开发者将日志信息以多种方式(数据库.控制台.文件等)输出的开源工具. 为什么要使用日志记录 提供应用程序运行时状态 ...
- 机器学习 —— 基础整理(八)循环神经网络的BPTT算法步骤整理;梯度消失与梯度爆炸
网上有很多Simple RNN的BPTT(Backpropagation through time,随时间反向传播)算法推导.下面用自己的记号整理一下. 我之前有个习惯是用下标表示样本序号,这里不能再 ...
- phpstudy:80端口被占用解决方案总结
一开始因为要安装新的软件,同时也由于一直电脑很卡,所以直接重装系统,从WIN8变成WIN10,然后不知道为什么,phpstudy里面80端口被占用了!被占用了!现在找到了两种方法解决! 第一种 该端口 ...
- css阴影,边框,渐变,背景
一.box-shadow: 参数1,参数2 阴影位置偏移量 参数3 模糊半径 参数4 扩展半径 负数 0 默认值 正数 参数5 阴影的颜色 参数6 设置内阴影 inset 默认是外阴影 多个阴影使用, ...
- 解决 CefSharp WPF控件不能使用输入法输入中文的问题(代码已提交到 github)
首先,本文所有 代码已经提交到github,需要的可以直接从github获取:https://github.com/starts2000/CefSharp,希望可以帮助到有需要的朋友们. CEF 简介 ...
- 【原创】07. ajax请求,解决sendRedirect 无效
介绍: 后台基于旧代码用的Filter验证,若 Session过期,则跳转登陆页面 前台框架:EasyUI 问题: 最初后台验证不通过: 1 httpServletResponse.sendRedir ...
- oracle 审计日志清理
--进入审计日志目录: cd $ORACLE_BASE/admin/$ORACLE_SID/adump --删除3个月前的审计文件: find ./ -type f -name "*.a ...