我继续用Coder和Designer的例子来理解桥接设计模式
首先我们知道:
我们的工作可以大致分为两个维度:
1 职位的不同,有码农,有设计师
2 有两个不同方向的开发公司 java IOS
我们也许会这么处理,用一个Employee作为总的抽象类,然后分为Coder 和 Designer, 然后Coder分为两个方向,JAVA 和 IOS
如图:
这样的继承结构是比较不合理的,我们设计模式有个原则是 合成复用原则,这样的设计继承层次比较多,我们应该在抽象类上做功夫。
桥接模式:将抽象部分和现实部分分离,使他们可以独立的变化。 (概念)
桥接模式是一种结构型设计模式,主要是针对类与类之间的关系作出的设计。不要和创建型设计模式搞混淆了。
这里的抽象部分其实就是: 职位和方向。
让职位和方向去应对变化。
类图设计:
设计代码:
package bridge;
//Abstraction 抽象类
public abstract class Language {
//这只是一个方向,当然要Worker用它了 所以引用一个Work 至于是什么Work这里是不关心的
private Worker work;
public void setWork(Worker work) {
this.work = work;
}
public Language(Worker w) {
this.work=w;
}
public Worker getWork() {
return work;
}
public abstract void use();
}
package bridge;
//RefinedAbstraction 扩展抽象类
public class JAVA extends Language {
public JAVA(Worker w) {
super(w);
}
@Override
public void use() {
getWork().work();
System.out.print("JAVA项目");
}
}
package bridge;
//RefinedAbstraction 扩展抽象类
public class IOS extends Language {
public IOS(Worker w) {
super(w);
}
@Override
public void use() {
this.getWork().work();
System.out.print("IOS项目");
}
}
package bridge;
//implementor 实现化角色
public interface Worker {
public void work();
}
package bridge;
//具体实现类
public class Coder implements Worker{
//程序员可以写代码
@Override
public void work() {
System.out.print("程序员在写");
}
}
package bridge;
public class Designer implements Worker{
//设计者可以设计
@Override
public void work() {
System.out.print("设计师在设计");
}
}
package bridge;
public class Test {
public static void main(String[] args) {
Worker coder = new Coder();
Worker designer = new Designer();
Language language = new IOS(coder);
Language language2 = new JAVA(designer);
language.use();
System.out.println();
language2.use();
}
}
再回来分析桥接模式的概念
将抽象部分和现实部分分离,使他们可以独立的变化 我们将抽象的woker 和 Language来进行聚合 来应对变化了,这满足了设计原则中的接口隔离原则(Language和work接口是不相干的)和依赖倒转原则(高层模块不应该依赖低层模块,二者都应该依赖其抽象,language依赖于work 而不是具体的实现类;抽象不应该依赖细节;细节应该依赖抽象,language中不依赖于具体的work实现类,work具体实现肯定是依赖于work接口的)
当我们有新的需求的时候,比如JAVA需要变化 ,不用改变原来的抽象类,这满足了开闭原则
如果我们要扩展任何一个维度,增加一个实现子类就好了,如PHP 或者 测试人员
上一个例子如果没有充分说明,接下来再举一个例子:
如果 MyBridge是一公司: 公司 需要不同的人才 ,那么我们的公司Bridge接口进行编程 将抽象和现实进行解耦:
package bridge;
//Abstraction 抽象类
public abstract class Bridge {
//公司需要员工来工作 不同的需求需要不同的工作人员
private Worker work;
public void setWork(Worker work) {
this.work = work;
}
public Worker getWork() {
return work;
}
public Bridge(Worker w) {
this.work=w;
}
public abstract void use();
}
package bridge;
public class MyBridge extends Bridge{
public MyBridge(Worker w) {
super(w);
}
@Override
public void use() {
System.out.print("公司需要");
this.getWork().work();
}
}
其他抽象类和实现子类和上一个例子一样
Client:
package bridge;
public class Test {
public static void main(String[] args) {
Worker coder = new Coder();
Worker designer = new Designer();
Bridge bridge = new MyBridge(coder);
bridge.use();
bridge.setWork(designer);
System.out.println();
bridge.use();
}
}
桥接的用意是:将抽象化与实现化解耦,使得二者可以独立变化,像我们常用的JDBC桥DriverManager一样,JDBC进行连接数据库的时候,在各个数据库之间进行切换,基本不需要动太多的代码,甚至丝毫不用动,原因就是JDBC提供统一接口,每个数据库提供各自的实现,用一个叫做数据库驱动的程序来桥接就行了。