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 ...
随机推荐
- http请求的GET和POST请求:查询和新增(server.php)
<?php //设置页面内容是html编码格式是utf-8 header("Content-Type: text/plain;charset=utf-8"); //heade ...
- Spring报错: org.springframework.beans.factory.support.BeanDefinitionValidationException: Couldn't find an init method named 'init' on bean with name 'car'(待解答)
在Spring工程里,有一个Car类的bean,Main.java主程序,MyBeanPostProcessor.java是Bean后置处理器. 文件目录结构如下: Car.java package ...
- Sqlserver 存储过程 返回-6
存储过程中没有返回 手动返回-6的代码,但是一直接收到-6返回值. 经最后研究发现,是粗心导致的,Insert插入数据时在非空字段插入了Null值导致出现异常,所以返回了-6. 所以说在事务中,可能会 ...
- Linux:join命令详解
join 处理两个文件之间的数据,并且将两个文件中有相同的数据的那一行加在一起 语法 join(选项)(file1 file2) 选项 -a<1或2>:除了显示原来的输出内容之外,还显示指 ...
- 【转】DirectUI 资源提取器
转自 http://www.cnblogs.com/Alberl/p/3378413.html 二.DirectUI 资源提取器 由于不能用传统工具,那么怎么办呢?可能有很多网友都知道QQ ...
- 微信小程序的一些数据调用方式
1.模板数据的调用 一张图了解一下在wxml页调用预先定义好的模板: 可以看到上面调用了两个模板,数据调用却是不同的,obj是一个对象,对象内包含多个键值对形式的数据: tabbar是一个一维数组,每 ...
- 向量点积(Dot Product),向量叉积(Cross Product)
参考的是<游戏和图形学的3D数学入门教程>,非常不错的书,推荐阅读,老外很喜欢把一个东西解释的很详细. 1.向量点积(Dot Product) 向量点积的结果有什么意义?事实上,向量的点积 ...
- 实现Python代码发送邮件
import smtplib from email.mime.text import MIMEText from email.utils import formataddr msg = MIMETex ...
- 【剑指offer】04A二维数组中的查找,C++实现
1.题目 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数数组和一个整数,判断数组中是否含有该整数. 2.思路 首先选取数 ...
- kubeadm搭建kubernetes集群之二:创建master节点
在上一章kubeadm搭建kubernetes集群之一:构建标准化镜像中我们用VMware安装了一个CentOS7虚拟机,并且打算用这个虚拟机的镜像文件作为后续整个kubernetes的标准化镜像,现 ...