GOF23设计模式之桥接模式(bridge)
一、桥接模式概述
桥接模式核心要点:
处理多层继承结构,处理多维度变化的场景,将各个维度设计成独立的继承结构,使各个维度可以独立的扩展在抽象层建立关联。
二、桥接模式场景提出与存在问题
商城系统中常见的商品分类,以电脑为类,如何良好的处理商品分类销售的问题?
这个场景中有两个变化的维度:品牌、电脑类型。

(1)不使用桥接模式时:
/**
* 不适用桥接模式时的电脑产品按照类型和品牌分类
* @author CL
*
*/
public interface Computer {
void sale();
} /**
* 类型:台式机
* @author CL
*
*/
class Desktop implements Computer { @Override
public void sale() {
System.out.println("销售台式机");
} } /**
* 类型:笔记本
* @author CL
*
*/
class Laptop implements Computer { @Override
public void sale() {
System.out.println("销售笔记本");
} } /**
* 类型:平板
* @author CL
*
*/
class Pad implements Computer { @Override
public void sale() {
System.out.println("销售平板电脑");
} } /**
* 品牌:联想台式机
* @author CL
*
*/
class LenovoDesktop extends Desktop {
@Override
public void sale() {
System.out.println("销售联想台式机");
}
} /**
* 品牌:联想笔记本
* @author CL
*
*/
class LenovoLaptop extends Desktop {
@Override
public void sale() {
System.out.println("销售联想笔记本");
}
} /**
* 品牌:联想平板电脑
* @author CL
*
*/
class LenovoPad extends Desktop {
@Override
public void sale() {
System.out.println("销售联想平板电脑");
}
} /**
* 品牌:戴尔台式机
* @author CL
*
*/
class DellDesktop extends Desktop {
@Override
public void sale() {
System.out.println("销售戴尔台式机");
}
} /**
* 品牌:戴尔笔记本
* @author CL
*
*/
class DellLaptop extends Desktop {
@Override
public void sale() {
System.out.println("销售戴尔笔记本");
}
} /**
* 品牌:戴尔平板电脑
* @author CL
*
*/
class DellPad extends Desktop {
@Override
public void sale() {
System.out.println("销售戴尔平板电脑");
}
} /**
* 品牌:华硕台式机
* @author CL
*
*/
class ASUSDesktop extends Desktop {
@Override
public void sale() {
System.out.println("销售华硕台式机");
}
} /**
* 品牌:华硕笔记本
* @author CL
*
*/
class ASUSLaptop extends Desktop {
@Override
public void sale() {
System.out.println("销售华硕笔记本");
}
} /**
* 品牌:华硕平板电脑
* @author CL
*
*/
class ASUSPad extends Desktop {
@Override
public void sale() {
System.out.println("销售华硕平板电脑");
}
}
测试:
/**
* 客户端
* @author CL
*
*/
public class Client { public static void main(String[] args) {
Computer c1 = new LenovoDesktop();
c1.sale();
} }
控制台输出:
销售联想台式机
(2)存在问题
① 扩展性问题(类的个数膨胀问题)
如果要增加一个新的电脑类型,如智能手机,则要增加各个品牌下面的类;
如果要增加一个新的品牌,也要增加各种电脑类型的类。
② 违反了单一职责原则
一个类有两个职责:品牌+电脑类型。每个类都有两个原因引起变化。
三、桥接模式应用
(1)电脑类型维度
/**
* 维度:电脑类型
* @author CL
*
*/
public class Computer {
protected Brand brand; public Computer(Brand brand) {
this.brand = brand;
} public void sale() {
brand.sale();
}
} /**
* 台式机
* @author CL
*
*/
class Desktop extends Computer { public Desktop(Brand brand) {
super(brand);
} @Override
public void sale() {
super.sale();
System.out.println("销售台式机");
}
} /**
* 笔记本
* @author CL
*
*/
class Laptop extends Computer { public Laptop(Brand brand) {
super(brand);
} @Override
public void sale() {
super.sale();
System.out.println("销售笔记本");
}
} /**
* 平板电脑
* @author CL
*
*/
class Pad extends Computer { public Pad(Brand brand) {
super(brand);
} @Override
public void sale() {
super.sale();
System.out.println("销售平板电脑");
}
}
(2)品牌维度
/**
* 一种维度:品牌
* @author CL
*
*/
public interface Brand {
void sale();
} /**
* 联想电脑
* @author CL
*
*/
class Lenovo implements Brand { @Override
public void sale() {
System.out.println("销售联想电脑");
} } /**
* 戴尔电脑
* @author CL
*
*/
class Dell implements Brand { @Override
public void sale() {
System.out.println("销售戴尔电脑");
} } /**
* 华硕电脑
* @author CL
*
*/
class ASUS implements Brand { @Override
public void sale() {
System.out.println("销售华硕电脑");
} }
(3)测试
/**
* 客户端
* @author CL
*
*/
public class Client { public static void main(String[] args) {
//销售联想笔记本电脑
Computer c1 = new Laptop(new Lenovo());
c1.sale(); //销售戴尔台式机
Computer c2 = new Desktop(new Dell());
c2.sale();
} }
控制台输出:
销售联想电脑
销售笔记本
销售戴尔电脑
销售台式机
(4)假如现在要在品牌维度上增加一种品牌:宏碁电脑,只需要在品牌维度中增加如下代码:
/**
* 宏碁电脑
* @author CL
*
*/
class Acer implements Brand { @Override
public void sale() {
System.out.println("销售宏碁电脑");
} }
(5)测试
/**
* 客户端
* @author CL
*
*/
public class Client { public static void main(String[] args) {
//销售联想笔记本电脑
Computer c1 = new Laptop(new Lenovo());
c1.sale(); //销售戴尔台式机
Computer c2 = new Desktop(new Dell());
c2.sale(); //销售宏碁的平板电脑
Computer c3 = new Pad(new Acer());
c3.sale();
} }
控制台输出:
销售联想电脑
销售笔记本
销售戴尔电脑
销售台式机
销售宏碁电脑
销售平板电脑
四、桥接模式总结
(1)桥接模式可以取代多层继承的方案。
多层继承违背了单一职责原则,复用性较差,类的个数也非常多。桥接模式可以极大的减少子类的个数,从而降低管理和维护的成本。
(2)桥接模式极大的提高了系统的可扩展性。
在两个变化的维度中任意扩展一个维度。都不需要修改原有的代码,符合开闭原则。
五、桥接模式实际开发中的应用场景
(1)JDBC驱动程序;
(2)AWT中的Peer框架;
(3)人力资源系统中的奖金计算模块:
奖金分类:个人奖金、团队奖金、激励奖金
部门分类:开发部门、运维部门、人事部门
(4)OA系统中的消息处理:
业务类型:普通消息、加密消息、紧急消息
发送方式:系统内部、手机短信、邮件、飞秋
(5)…………
GOF23设计模式之桥接模式(bridge)的更多相关文章
- 乐在其中设计模式(C#) - 桥接模式(Bridge Pattern)
原文:乐在其中设计模式(C#) - 桥接模式(Bridge Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 桥接模式(Bridge Pattern) 作者:webabcd 介绍 ...
- 【设计模式】桥接模式 Bridge Pattern
开篇还是引用吕振宇老师的那篇经典的文章<设计模式随笔-蜡笔与毛笔的故事>.这个真是太经典了,没有比这个例子能更好的阐明桥接模式了,这里我就直接盗来用了. 现在市面上卖的蜡笔很多,各种型号, ...
- python 设计模式之桥接模式 Bridge Pattern
#写在前面 前面写了那么设计模式了,有没有觉得有些模式之间很类似,甚至感觉作用重叠了,模式并不是完全隔离和独立的,有的模式内部其实用到了其他模式的技术,但是又有自己的创新点,如果一味地认为每个模式都是 ...
- 二十四种设计模式:桥接模式(Bridge Pattern)
桥接模式(Bridge Pattern) 介绍将抽象部分与它的实现部分分离,使它们都可以独立地变化. 示例有一个Message实体类,对它的操作有Insert()和Get()方法,现在使这些操作的抽象 ...
- 【GOF23设计模式】桥接模式
来源:http://www.bjsxt.com/ 一.[GOF23设计模式]_桥接模式.多层继承结构.银行日志管理.管理系统消息管理.人力资源的奖金计算 未用桥接模式: package com.te ...
- [设计模式] 7 桥接模式 bridge
#include<iostream> using namespace std; class AbstractionImp { public: virtual ~AbstractionImp ...
- 设计模式之桥接模式(Bridge)--结构模型
1.意图 将抽象部分与它的实现部分分离,使它们可以独立地变化. 2.适用性 你不希望在抽象和它的实现部分之间有一个固定的绑定关系. 类的抽象与它的实现都应该可以通过子类的方式加以扩展. 抽象部分与实现 ...
- 设计模式 笔记 桥接模式 Bridge
//---------------------------15/04/15---------------------------- //Bridge 桥接模式----对象结构型模式 /* 1:意图:将 ...
- 设计模式之桥接模式(Bridge)
桥接模式与原理:将抽象部分与实现部分分离,使它们都可以独立的变化.最终的结果表现在实现类中.两者之间属于等价关系,即实现部分和抽象部分可以相互交换. 代码如下 #include <iostrea ...
随机推荐
- 微信小程序获取当前页面的路径的方式
使用getCurrentPages可以获取当前加载中所有的页面对象的一个数组,数组最后一个就是当前页面. var pages = getCurrentPages() //获取加载的页面 var cur ...
- laravel中新建文件并保存数据到文件中
//base_path()获取当前的绝对路径 $path=base_path().'\config\web.php'; $str='abcdefg'; //要声明的字符串 file_put_conte ...
- CentOS 6.5 升级内核到 3.10.28
本文适用于CentOS 6.4, CentOS 6.5,亲测可行,估计也适用于其他Linux发行版. 1. 准备工作 1.1 下载源码包 Linux内核版本有两种:稳定版和开发版 ,Linux内核版本 ...
- vue.js 源代码学习笔记 ----- 工具方法 props
/* @flow */ import { hasOwn, isObject, isPlainObject, capitalize, hyphenate } from 'shared/util' imp ...
- Unity3D使用溶解技术解决障碍物遮挡
笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D实战核心技术详解 ...
- chrome 中for-in 在遍历对象时的顺序问题
- Android Jni调用浅述
声明:欢迎转载,转载时请注明出处!http://blog.csdn.net/flydream0/article/details/7371692 1 简述 JNI是Java Native Interfa ...
- Markdown 效果测试
欢迎使用 Cmd - 在线 Markdown 编辑阅读器 \[ \int e^{-x^2 - y^2} dx = \sqrt{2 \pi} \] 我们理解您需要更便捷更高效的工具记录思想,整理笔记.知 ...
- BZOJ4974:[Lydsy1708月赛]字符串大师(逆模拟KMP)
题目描述 一个串T是S的循环节,当且仅当存在正整数k,使得S是T k Tk (即T重复k次)的前缀,比如abcd是abcdabcdab的循环节.给定一个长度为n的仅由小写字符构成的字符串S,请对于每 ...
- Git-Svn 建立工作目录
使用Git-SVN 建立工作目录 GIT-SVN可以以SVN的版本为基础, 实现”私有”的版本管理功能. 这样一些不成熟但又需要记录的版本就不必提交到SVN上, 而只在自己本地私有的版本里出现. 下面 ...