桥接模式:
核心要点:处理多层继承结构,处理多维度变化的场景,将各个维度设计成独立的继承结构,使各维度可以独立拓展,在抽象层建立关联。
想象一个场景:我们要买电脑,电脑分台式机,笔记本等;电脑又有品牌,联想惠普戴尔苹果等;那么要怎么来表示这些电脑呢?
先建立一个电脑类,有两个子类,台式机类和笔记本类;台式机类下又有联想台式机,惠普台式机,戴尔台式机...笔记本类下也有联想笔记本,惠普笔记本,戴尔笔记本......现在如果又出现一个品牌苹果,那么又需要去增加苹果台式机类,苹果笔记本类;如果又出现了掌上电脑,于是就要有联想掌上电脑,惠普掌上电脑......然后我们就疯了=-=
上帝说,来个模式解决它。于是就有了桥接模式...
我们能够清晰地看到一点,品牌和机型是两个独立变化的维度,就像表格一样:(本文示例参考自北京尚学堂Java教程,高淇)
联想 | 惠普 | 戴尔 | |
台式机 | |||
笔记本 |
我们先定义品牌:
public interface Brand {
void sale();
}
接口内只包含一个方法sale(),表示销售该品牌的电脑。
定义几个实现类:
class Lenovo implements Brand{
@Override
public void sale() {
System.out.print("销售联想品牌");
}
}
class Mac implements Brand{
@Override
public void sale() {
System.out.print("销售Mac品牌");
}
}
class Hp implements Brand{
@Override
public void sale() {
System.out.print("销售Hp品牌");
}
}
接着定义机型,机型类中持有品牌的引用,并通过构造函数传入。这个设计很合理,机型一定是有品牌的,你买一台笔记本,一定会问买的什么牌子的。
public class Computer {
protected Brand brand;
public Computer(Brand brand) {
super();
this.brand = brand;
}
public void sale() {
brand.sale();
}
}
品牌类定义为protected,方便子类使用,定义一个函数sale(),调用Brand的sale()函数
增加几个子类:
class Laptop extends Computer{
public Laptop(Brand brand) {
super(brand);
}
@Override
public void sale() {
super.sale();
System.out.println("笔记本");
}
}
class Desktop extends Computer{
public Desktop(Brand brand) {
super(brand);
}
@Override
public void sale() {
super.sale();
System.out.println("台式机");
}
}
子类中重写父类的sale()方法,调用父类的sale()并增加自己的相关操作。
最后测试一下:
public class Client {
public static void main(String[] args) {
Computer c = new Laptop(new Lenovo());
c.sale();
}
}
输出:
销售联想品牌笔记本
使用了桥接模式以后,如果想增加机型如掌上电脑,增加品牌如神舟,都相当简单。
总结:
桥接模式可以取代多重继承的方案,多重继承违反单一职责原则,复用性较差,类的个数也非常多。
桥接模式可以极大地减少子类的个数,从而降低管理和维护的成本。
桥接模式极大地提高了系统的可拓展性,在两个变化维度中任意拓展一个维度,都不需要修改原有的系统,符合开闭原则。