七:桥接模式(bridge)
1.问题引出:商城系统中很多商品分类,以电脑为例:台式机,笔记本,平板电脑等,我们可以通过下图描述其关系

通过上面的图会发现很多问题:
- 如果要增加一个新的电脑类型需要再增加各个品牌对应的类
- 如果要增加一个新的品牌,也要增加各个电脑类型的类
- 违反单一职责原则:一个类即表示品牌又表示是那种类型的电脑
2.场景分析
商城系统中常见的商品分类,以电脑为类,如何良好的处理商品分类销售的问题?这个场景中有两个变化的维度:电脑类型、电脑品牌。

3.桥接模式核心要点:处理多层继承结构,处理多维度变化的场景,将各个维度设计成独立 的继承结构,使各个维度可以独立的扩展在抽象层建立关联。
4.案例:
/**
* 品牌接口
*/
public interface Brand {
void sale();
}
/**
* 联想品牌
*/
class Lenovo implements Brand{
@Override
public void sale() {
System.out.println("联想电脑......");
}
}
/**
* 戴尔品牌
*/
class Dell implements Brand{
@Override
public void sale() {
System.out.println("戴尔电脑......");
}
}
/**
* 电脑抽象类,表示电脑类型
*/
public abstract class Computer {
//绑定品牌
protected Brand brand;
public Computer(Brand brand) {
super();
this.brand = brand;
}
public void sale(){
brand.sale();
}
}
/**
* 台式机
*/
class DeskTop extends Computer{
public DeskTop(Brand brand) {
super(brand);
}
@Override
public void sale() {
super.sale();
System.out.println("销售台式机........");
}
}
/**
* 笔记本
*/
class LapTop extends Computer{
public LapTop(Brand brand) {
super(brand);
}
@Override
public void sale() {
super.sale();
System.out.println("销售笔记本.........");
}
}
public class Client {
public static void main(String[] args) {
//销售联想笔记本,组合代理继承关系
Computer lapTop = new LapTop(new Lenovo());
lapTop.sale();
//新加品牌只需要增加一个Brand的实现类
//新加平板只需要加一个Computer的子类
Computer pinban = new Pinban(new Shenzhou());
pinban.sale();
//不同组合
DeskTop deskTop = new DeskTop(new Shenzhou());
deskTop.sale();
}
}
class Shenzhou implements Brand{
@Override
public void sale() {
System.out.println("神州笔记本........");
}
}
class Pinban extends Computer{
public Pinban(Brand brand) {
super(brand);
}
@Override
public void sale() {
super.sale();
System.out.println("销售平板电脑......");
}
}
这样实现各个类实现单一原则,增加电脑时,只需要添加对应的品牌就电脑类型的实现即可。
5.桥接模式总结:
- 桥接模式可以取代多层继承的方案。 多层继承违背了单一职责原则, 复用性较差,类的个数也非常多。桥接模式可以极大的减少子类的个 数,从而降低管理和维护的成本。
- 桥接模式极大的提高了系统可扩展性,在两个变化维度中任意扩展一 个维度,都不需要修改原有的系统,符合开闭原则。
6.应用场景:划分维度两个及以上就适合用桥接模式,比如电脑有品牌,类型等
- 银行日志管理:格式分类:操作日志、交易日志、异常日志,距离分类:本地记录日志、异地记录日志
- 人力资源系统中的奖金计算模块:奖金分类:个人奖金、团体奖金、激励奖金。部门分类:人事部门、销售部门、研发部门。
- OA系统中的消息处理:业务类型:普通消息、加急消息、特急消息。发送消息方式:系统内消息、手机短信、邮件
八:组合模式(composite)
1.组合模式:把部分和整体的关系用树形结构来表示,从而使客户端可以使用统一的方式处理部分对 象和整体对象。
2.组合模式核心
- 抽象构件(Component)角色: 定义了叶子和容器构件的共同点
- 叶子(Leaf)构件角色:无子节点
- 容器(Composite)构件角色: 有容器特征,可以包含子节点
3.组合模式工作流程分析:
- 组合模式为处理树形结构提供了完美的解决方案,描述了如何将容器和叶子进行递归组 合,使得用户在使用时可以一致性的对待容器和叶子。
- 当容器对象的指定方法被调用时,将遍历整个树形结构,寻找也包含这个方法的成员, 并调用执行。其中,使用了递归调用的机制对整个结构进行处理。
4.案例
//抽象构建
public interface AbstractFile {
void killVirus();
}
//图片文件(叶子构建)
class ImageFile implements AbstractFile{
@Override
public void killVirus() {
System.out.println("图片文件删除了........");
}
}
//文本文件(叶子构建)
class TxtFile implements AbstractFile{
@Override
public void killVirus() {
System.out.println("文本文件删除了........");
}
}
//视频文件(叶子构建)
class VideoFile implements AbstractFile{
@Override
public void killVirus() {
System.out.println("视频文件删除了........");
}
}
//文件夹(容器构建)
class Folder implements AbstractFile{
//存储文件夹下的文件
private List<AbstractFile> fileList=new ArrayList<AbstractFile>();
//添加文件
public void add(AbstractFile abstractFile){
fileList.add(abstractFile);
}
//删除文件
public void remove(AbstractFile abstractFile){
fileList.remove(abstractFile);
}
//获取文件
public AbstractFile get(int index){
return fileList.get(index);
}
@Override
public void killVirus() {
System.out.println("文件夹杀毒开始.......");
for (AbstractFile abstractFile : fileList) {
//递归
abstractFile.killVirus();
}
}
}
public class Client {
public static void main(String[] args) {
//创建文件
AbstractFile imageFile = new ImageFile();
AbstractFile txtFile = new TxtFile();
AbstractFile videoFile = new VideoFile();
//创建文件夹
Folder folder = new Folder();
folder.add(imageFile);
folder.add(txtFile);
folder.add(videoFile);
//创建子文件夹
Folder folder2 = new Folder();
AbstractFile imageFile2 = new ImageFile();
folder2.add(imageFile2);
folder.add(folder2);
//杀毒文件夹,递归调用子文件及子文件夹的killVirus()方法
folder.killVirus();
}
}
树状结构都是用于组合模式
5.适用场景:
- 操作系统的资源管理器
- GUI中的容器层次图
- XML文件解析
- OA系统中,组织结构的处理
九:装饰模式(decorator)
1.作用:
- 动态为一个对象增加新的功能
- 装饰模式是一种用来代替继承的技术,无需通过继承增加子类就能扩展对象的新功能,适用对象关联关系代替继承关系,更加灵活,同时避免类型体系的快速膨胀。
2.案例:
/**
* 抽象接口
*/
public interface ICar {
void move();
}
//被装饰对象
class Car implements ICar{
@Override
public void move() {
System.out.println("陆地上跑.......");
}
}
//装饰器
class SuperCar implements ICar{
public ICar car;
public SuperCar(ICar car) {
super();
this.car = car;
}
@Override
public void move() {
car.move();
}
}
//具体装饰器,会飞的车
class FlyCar extends SuperCar{
public FlyCar(ICar car) {
super(car);
}
@Override
public void move() {
super.move();
fly();
}
public void fly() {
System.out.println("天上飞......");
}
}
//具体装饰器,会游泳的车
class WaterCar extends SuperCar{
public WaterCar(ICar car) {
super(car);
}
@Override
public void move() {
super.move();
water();
}
public void water() {
System.out.println("水上游......");
}
}
//具体装饰器,人工智能的车
class AICar extends SuperCar{
public AICar(ICar car) {
super(car);
}
@Override
public void move() {
super.move();
ai();
}
public void ai() {
System.out.println("自动跑......");
}
}
public class Client {
public static void main(String[] args) {
//一般车
Car car = new Car();
car.move();
//添加新的功能
FlyCar flyCar = new FlyCar(car);
flyCar.move();
//添加复合的功能
WaterCar waterCar = new WaterCar(flyCar);
waterCar.move();
//添加复合的功能
AICar aiCar = new AICar(waterCar);
aiCar.move();
}
}
功能可以自由组合
3.总结:
- 装饰模式(Decorator)也叫包装器模式(Wrapper)
- 装饰模式降低系统的耦合度,可以动态的增加或删除对象的职责,并 使得需要装饰的具体构建类和具体装饰类可以独立变化,以便增加新 的具体构建类和具体装饰类。
4.优点:
- 扩展对象功能,比继承灵活,不会导致类个数急剧增加
- 可以对一个对象进行多次装饰,创造出不同行为的组合,得到功能更 加强大的对象
- 具体构建类和具体装饰类可以独立变化,用户可以根据需要自己增加 新的具体构件子类和具体装饰子类。
5.缺点:
- 产生很多小对象。大量小对象占据内存,一定程度上影响性能。
- 装饰模式易于出错,调试排查比较麻烦。
6.装饰模式和桥接模式的区别:两个模式都是为了解决过多子类对象问题。但他们的诱因不一样。桥接模式是对象自身现有机制沿着多个维度变化,是既有部分不稳定。装饰模式是为了增加新的功能。
十:外观模式(facade)
1.迪米特法则(最少知识原则):一个软件实体应当尽可能少的与其他实体发生相互作用。

例如喝茶,尽可能的减少与茶具,水,茶叶关联,而是直接调用“茶馆服务员”就干完所有的事,外观模式就是解决这种问题的。
2.外观模式核心:为子系统提供统一的入口。封装子系统的复杂性,便于客户端调用。
3.案例:略
4.应用场景:JDBC封装后的,commons提供的DBUtils类, Hibernate提供的工具类、Spring JDBC工具类等
十一:享元模式(FlyWeight)
1.使用场景:内存属于稀缺资源,不要随便浪费。如果有很多个完全相同或相似的 对象,我们可以通过享元模式,节省内存。
2.核心:
- 享元模式以共享的方式高效地支持大量细粒度对象的重用。
- 享元对象能做到共享的关键是区分了内部状态和外部状态。内部状态:可以共享,不会随环境变化而改变,外部状态:不可以共享,会随环境变化而改变
3.案例:围棋(棋子颜色为内部对象可共享,棋子位置外部对象,不可共享)
//享元类,棋子颜色,内部状态,可共享
public interface ChessFlyWeight {
//获取棋子颜色
String getColor();
//显示棋子
void display(Coordinate coordinate);
}
//具体享元类对象
class ConcreteChess implements ChessFlyWeight{
private String color;
public ConcreteChess(String color) {
super();
this.color = color;
}
@Override
public String getColor() {
return color;
}
@Override
public void display(Coordinate coordinate) {
System.out.println(color+"\t"+coordinate.getX()+"\t"+coordinate.getY());
}
}
//棋子地址,外部状态,不可共享
public class Coordinate {
private int x,y;
//全参构造,get,set
}
//享元工厂,创建享元类
public class ChessFlyWeightFactory {
//享元池对象
public static Map<String, ChessFlyWeight> map=new HashMap<String, ChessFlyWeight>();
//获取棋子
public static ChessFlyWeight getChessFlyWeight(String color) {
if (map.containsKey(color)) {
return map.get(color);
}
ChessFlyWeight chessFlyWeight = new ConcreteChess(color);
map.put(color, chessFlyWeight);
return chessFlyWeight;
}
public static void main(String[] args) {
ChessFlyWeight black1 = ChessFlyWeightFactory.getChessFlyWeight("black");
ChessFlyWeight black2 = ChessFlyWeightFactory.getChessFlyWeight("black");
System.out.println(black1);//对象相同
System.out.println(black2);
//内部对象相同,外部对象不相同
black1.display(new Coordinate(10, 10));//black 10 10
black2.display(new Coordinate(20,100));//black 20 100
}
}
4.优点:
- 极大减少内存中对象的数量
- 相同或相似对象内存中只存一份,极大的节约资源,提高系统性能
- 外部状态相对独立,不影响内部状态
5.缺点:
- 模式较复杂,使程序逻辑复杂化
- 为了节省内存,共享了内部状态,分离出外部状态,而读取外部状态 使运行时间变长。用时间换取了空间。
十二:责任链模式(chain of responsibility)
1.定义:能够处理同一类请求的对象连成一条链,所提交的请求沿着链传递,链上的对象逐个判断是否有能力处理该请求,如果能则处理,否则传递给链上的下一个对象。
2.案例:公司请假为例,层层审批
//假条,封装请假基本信息
public class LaveRequest {
private String name;//请假人名称
private int days;//请假天数
private String reason;//请假原因
//全参构造,get,set
}
//抽象类,描述各级领导
public abstract class Leader {
protected String name;//领导名称
protected Leader nextLeader;//上级领导
//处理请求
public abstract void handlerRequest(LaveRequest request);
public Leader(String name, Leader nextLeader) {
super();
this.name = name;
this.nextLeader = nextLeader;
}
public void setNextLeader(Leader nextLeader) {
this.nextLeader = nextLeader;
}
}
//主任
class Director extends Leader{
public Director(String name, Leader nextLeader) {
super(name, nextLeader);
}
@Override
public void handlerRequest(LaveRequest request) {
if (request.getDays()<3) {
System.out.println("主任允许啦......");
return;
}
nextLeader.handlerRequest(request);
}
}
//经理
class Manager extends Leader{
public Manager(String name, Leader nextLeader) {
super(name, nextLeader);
}
@Override
public void handlerRequest(LaveRequest request) {
if (request.getDays()<10) {
System.out.println("经理允许啦......");
return;
}
nextLeader.handlerRequest(request);
}
}
//总经理
class GeneralMamager extends Leader{
public GeneralMamager(String name, Leader nextLeader) {
super(name, nextLeader);
}
@Override
public void handlerRequest(LaveRequest request) {
if (request.getDays()<30) {
System.out.println("总经理允许啦......");
return;
}
System.out.println("不同意.......");
}
}
public class Client {
public static void main(String[] args) {
LaveRequest laveRequest = new LaveRequest("张三", 1, "就是想请假");
Leader generalMamager = new GeneralMamager("李四", null);
Leader manager = new Manager("王五", generalMamager);
Leader director = new Director("赵六",manager);
director.handlerRequest(laveRequest);
//如果想要添加其他链的节点,只需要新加一个Leader实现类,加入到链中即可
}
}
由于责任链的创建完全在客户端,因此新增新的具体处理者对原有类库没有任何影响,只需添加新的类,然后在客户端调用时添加即可。 符合开闭原则。
3.应用场景:
- Java中,异常机制就是一种责任链模式。一个try可以对应多个catch, 当第一个catch不匹配类型,则自动跳到第二个catch.
- Javascript语言中,事件的冒泡和捕获机制。Java语言中,事件的处理 采用观察者模式。
- Servlet开发中,过滤器的链式处理
- Struts2中,拦截器的调用也是典型的责任链模式
十三:迭代器模式(iterator)
提供一种可以遍历聚合对象的方式。又称为:游标cursor模式 ,聚合对象:存储数据 ,迭代器:遍历数据
案例:
//迭代器接口
public interface MyIterator {
void first();//将游标指向第一个
void next();//将游标指向下一个
boolean hasNext();//判断是否有下一个元素
Object get();//获取当前对象
}
//自定义聚合类
public class ConcreteMyAggregqte {
private List<String> list=new ArrayList<String>();
public void add(String s) {
list.add(s);
}
public void remove(String s) {
list.remove(s);
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
public MyIterator iterator() {
return new Iterator();
}
private class Iterator implements MyIterator{
//游标
private int cursor=0;
@Override
public void first() {
cursor=0;
}
@Override
public void next() {
if (cursor<list.size()-1) {
++cursor;
}
}
@Override
public boolean hasNext() {
return cursor<=list.size()-1;
}
@Override
public Object get() {
String string = list.get(cursor);
cursor++;
return string;
}
}
public static void main(String[] args) {
ConcreteMyAggregqte concreteMyAggregqte = new ConcreteMyAggregqte();
concreteMyAggregqte.add("aa");
concreteMyAggregqte.add("bb");
concreteMyAggregqte.add("cc");
MyIterator iterator = concreteMyAggregqte.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.get());
}
}
}
十四:中介者模式(mediator)
1.特点:如果一个系统的对象之间关系呈现网状结构,对象之间呈现大量的多对多关系,将导致关系特别复杂,这些对象称为“同事对象”,引入中介者对象,使各个对象跟中介者打交道,将复杂的网状结构转化为星状结构。
2.案例:总经理与各部门之间的关系,总经理就是中介者
/**
* 中介者接口
*/
public interface Mediator {
//部门注册
void register(String dname,Department department);
//指定部门干活
void command(String dname);
}
//总经理
class Pre implements Mediator{
private Map<String, Department> map=new HashMap<String, Department>();
@Override
public void register(String dname, Department department) {
map.put(dname, department);
}
@Override
public void command(String dname) {
Department department = map.get(dname);
department.selfAction();
}
}
/**
* 部门接口
*/
public interface Department {
//干自己部门的活
void selfAction();
//让总经理协调干活
void outAction();
}
//研发部
class Dev implements Department{
private Mediator mediator;
public Dev(Mediator mediator) {
super();
this.mediator = mediator;
mediator.register("Dev", this);
}
@Override
public void selfAction() {
System.out.println("研发部开始研发啦........");
}
@Override
public void outAction() {
System.out.println("研发部汇报工作........");
}
}
//财务部
class Fin implements Department{
private Mediator mediator;
public Fin(Mediator mediator) {
super();
this.mediator = mediator;
mediator.register("Fin", this);
}
@Override
public void selfAction() {
System.out.println("财务部开始数钱啦........");
}
@Override
public void outAction() {
System.out.println("财务部汇报工作........");
}
}
//财务部
class Mar implements Department{
private Mediator mediator;
public Mar(Mediator mediator) {
super();
this.mediator = mediator;
mediator.register("Mar", this);
}
@Override
public void selfAction() {
System.out.println("市场部开始拓展市场啦........");
}
@Override
public void outAction() {
System.out.println("市场部汇报工作,需要资金支持........");
mediator.command("Fin");//财务部支持
}
}
public class Client {
public static void main(String[] args) {
Mediator pre = new Pre();
Department dev = new Dev(pre);
Department fin = new Fin(pre);
Department mar = new Mar(pre);
mar.selfAction();
mar.outAction();//经过总经理协调,财务部开始数钱啦
}
}
3.中介者模式的本质:解耦多个同事对象之间的交互关系。每个对象都持有中介者对象的引 用,只跟中介者对象打交道。我们通过中介者对象统一管理这些交互 关系
十五:命令模式(command)
1.介绍:将一个请求(命令相当于一个请求)封装为一个对象,从而使我们可以用不同的请求对客户进行参数化,对请求排队或记录日志,以及支持可撤销操作,也称为“动作Action模式,事务transaction模式”
2.案例
//命令执行者
public class Recelver {
public void action(){
System.out.println("action.......");
}
}
//命令接口
public interface Command {
//执行方法
void execute();
}
//命令实现
class ConcreteCommand implements Command{
private Recelver recelver;
public ConcreteCommand(Recelver recelver) {
super();
this.recelver = recelver;
}
@Override
public void execute() {
System.out.println("命令执行前......");
recelver.action();
System.out.println("命令执行后......");
}
}
//命令发起者
public class Invaker {
//一条命令,多条通过容器
private Command command;
public Invaker(Command command) {
super();
this.command = command;
}
public void call(){
command.execute();
}
public static void main(String[] args) {
//创建命令
Recelver recelver = new Recelver();
ConcreteCommand concreteCommand = new ConcreteCommand(recelver);
Invaker invaker = new Invaker(concreteCommand);
invaker.call();
}
}
3.应用场景:
- 数据库事务机制的底层实现
- Struts2中,action的整个调用过程中就有命令模式。
- 命令的撤销和恢复


被折叠的 条评论
为什么被折叠?



