22 桥接模式
1 定义
将抽象部分和它的实现部分分离,使它们都可以独立的变化。也就是说:实现系统可能会有多角度分类,每一种分类都有可能变化,那么就把这种多角度分离出来让他们独立变化,减少它们之间的耦合。
2 组合/聚合复用原则
2.1 组合和聚合的定义
- 组合(合成):强拥有关系,比如大雁和翅膀的关系,大雁拥有2只翅膀,翅膀是大雁的一部分,2者的声明周期是一样的。
- 聚合:弱拥有关系,比如雁群和大雁的关系,雁群由大雁组成,每个大雁都属于一个雁群。
2.2 合成/聚合复用原则
- 定义:尽量使用合成/聚合,尽量不要使用类继承。
- 好处:
- 保持每个类被封装
- 保持每个类集中在单个任务上。
- 这样类和类继承层次会保持较小的规模,并且不太可能增长为不可控制的庞然大物。用对象的职责,而不是结构考虑问题。
3 举个例子(手机的实现的方式)
- 可以通过先按照品牌分类,然后在品牌下再按照功能分类;
- 也可以先按照功能分类,然后每个功能下面再按照手机品牌分类;
关于手机的例子,通过继承实现的两种方式如下图:
因为手机品牌和有哪些功能都是经常变化的东西。所以在实现一个手机时,将手机品牌和手机功能独立实现
,而不是通过继承实现强耦合。这样在增加一个手机品牌or增加一个手机功能时,只需要添加一个类即可,曾经的代码并不需要改动,符合开放-封闭原则
;且实现了手机品牌和手机功能的解耦
。
由于实现的方式有多种,桥接模式的核心
就是把这些实现独立出来,让它们各自变化。这就使得每种实现的变化不会影响其他实现,从而达到应对变化的目的。
4 UML图
# 5 例子
5.1 场景
手机分品牌和功能,且品牌和功能经常发生变化。每个手机都有自己的品牌和功能。如何实现多个手机的构建过程?
5.2 UML图
5.3 code
Main
public class Main {
public static void main(String[] args) {
PhoneBrand brand;
//手机品牌1
System.out.println("----手机品牌A1----");
brand=new Brand1();
//软件:通讯录
brand.setSoftWare(new SoftWare1());
brand.run();
//软件:游戏
brand.setSoftWare(new SoftWare2());
brand.run();
//手机品牌2
System.out.println("----手机品牌A2----");
brand=new Brand2();
brand.setSoftWare(new SoftWare1());
brand.run();
brand.setSoftWare(new SoftWare2());
brand.run();
}
}
PhoneBrand
public abstract class PhoneBrand {
//持有软件的引用
protected PhoneSoftWare softWare;
public void setSoftWare(PhoneSoftWare softWare) {
this.softWare = softWare;
}
//调用软件功能方法
public abstract void run();
}
Brand1
public class Brand1 extends PhoneBrand {
@Override
public void run() {
super.softWare.run();
}
}
Brand2
public class Brand2 extends PhoneBrand {
@Override
public void run() {
super.softWare.run();
}
}
PhoneSoftWare
public abstract class PhoneSoftWare {
public abstract void run();
}
SoftWare1
public class SoftWare1 extends PhoneSoftWare {
@Override
public void run() {
System.out.println("手机通信录功能运行");
}
}
SoftWare2
public class SoftWare2 extends PhoneSoftWare {
@Override
public void run() {
System.out.println("手机游戏功能运行");
}
}
参考
https://blog.****.net/caoxiaohong1005/article/details/79167671