桥接模式
定义
将实现和抽象分离开,使它们可以单独独立地变化。这里的实现是可以在抽象类机及其子类上调用自己的具体类。
结构
Abstraction(抽象类):它可以是接口也可以是抽象类,定义了需要实现的方法。
ConcreteAbstraction(具体抽象类):它持有实现类的引用,实现方法中调用该引用的方法(复合+转发)。
Implementor(实现类):定义具体实现类的接口。
ConcreteImplementor(具体实现类):具体的实现。
类图
abstraction:
public interface Abstraction {
public void operation();
}
concreteabstraction:
public class ConcreteAbstraction implements Abstraction{
private Implementor implementor;
public ConcreteAbstraction(Implementor implementor) {
this.implementor = implementor;
}
@Override
public void operation() {
implementor.operation();
}
}
Implementor:
public abstract class Implementor {
public abstract void operation();
}
具体实现类A:
public class ConcreteImplementorA extends Implementor{
@Override
public void operation() {
System.out.println("执行A计划");
}
}
具体实现类B:
public class ConcreteImplementorB extends Implementor{
@Override
public void operation() {
System.out.println("执行B计划");
}
}
测试类:
public static void main(String[] args) {
Abstraction abstractionA = new ConcreteAbstraction(new ConcreteImplementorA());
abstractionA.operation();
Abstraction abstractionB = new ConcreteAbstraction(new ConcreteImplementorB());
abstractionB.operation();
}
测试结果:
案例
我将以不同手机品牌实现看电影、玩游戏接口为例,手机作为抽象类,不同品牌的手机作为具体抽象类,玩游戏、看电影作为具体实现类。
手机抽象类:
public abstract class AbstractionMobile {
public abstract void operation();
}
Nokia具体类:
public class NokiaMobile extends AbstractionMobile{
private ImplementFunction function;
public NokiaMobile(ImplementFunction function) {
this.function = function;
}
@Override
public void operation() {
function.operation();
}
}
实现抽象接口:
public abstract class ImplementFunction {
public abstract void operation();
}
玩游戏实现类:
public class playGameFunction extends ImplementFunction{
@Override
public void operation() {
System.out.println("玩游戏");
}
}
看电影实现类:
public class WatchMovieFunction extends ImplementFunction{
@Override
public void operation() {
System.out.println("看电影");
}
}
测试类:
public static void main(String[] args) {
System.out.println("nokia手机:");
NokiaMobile nokiaMobile1 = new NokiaMobile(new WatchMovieFunction());
nokiaMobile1.operation();
NokiaMobile nokiaMobile2 = new NokiaMobile(new playGameFunction());
nokiaMobile2.operation();
}
测试结果:
现在我们写好了nokia支持看电影、玩游戏。如果现在要对ZTE手机实现这些功能,那么只需要增加一个ZTE手机类。
ZTE手机类:
public class ZTEMobile extends AbstractionMobile{
private ImplementFunction function;
public ZTEMobile(ImplementFunction function) {
this.function = function;
}
@Override
public void operation() {
function.operation();
}
}
测试类:
public static void main(String[] args) {
System.out.println("ZTE手机:");
ZTEMobile zteMobile1 = new ZTEMobile(new WatchMovieFunction());
zteMobile1.operation();
ZTEMobile zteMobile2 = new ZTEMobile(new playGameFunction());
zteMobile2.operation();
}
测试结果:
优点
1.实现和抽象分离,降低耦合度
2.具体实现对客户端完全透明
3.可扩展、可复用
缺点
1.桥接模式的引入增加了系统的理解和设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计和编程。
2.桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围有一定的局限性。
JDK源码中的桥接模式
JDBC:jdbc是典型的桥接模式案例,它将抽象和实现分离开来,抽象是jdbc的api,而具体的实现就是不同的数据库驱动,它们之间互不影响。