一)故事
二)定义
将抽象和实现解耦,使得两者可以独立地变化。
三)代码例子
共计四个类:1)实现化角色;2)具体实现化角色(可多个);3)抽象化角色;4)具体抽象化角色(可多个);
1)实现化角色
2)具体实现化角色(可多个)
3)抽象化角色
4)具体抽象化角色(可多个)
场景使用例子:
1)增加公司,要么继承Corp类,要么继承HouseCorp或ShanZhaiCorp,不用再修改原有的类了。
2)增加产品,继承Product类,或者继承House类,你要把房子分为公寓房,别墅,商业用房等。
你唯一要修改的就是Client类。类都增加了,高层模式也需要修改,也就是说Corp类和Product类都可以自由地扩展,而不会对整个应用产生太大的变更,这就是桥梁模式。
四)优点
1)抽象与实现分离
这也是桥梁模式的主要特点,它完全是为了解决继承的缺点而提出的设计模式,在该模式下,实现可以不受抽象的约束,不用再绑定在一个固定的抽象层次上。
2)优秀的扩充能力
看看我们的例子,想增加实现?没问题!想增加抽象,也没有问题!只要对外暴露的接口层允许这样的变化,我们已经把变化的可能性减到最小。
3)实现细节对客户透明
客户不用关心细节的实现,它已经由抽象层通过聚合关系完成了封装。
五)缺点
六)使用场景
1)不希望或不适用使用继承的场景
例如继承层次过渡,无法更细化设计颗粒等场景,需要考虑使用桥梁模式。
2)接口或抽象类不稳定的场景
明知道接口不稳定还想通过实现或继承来实现业务需求,那是得不偿失的,也是比较失败的做法。
3)重用性要求较高的场景
设计的颗粒度超细,则被重用的可能性就越大,而采用继承则受父类的限制,不可能出现太细的颗粒度。
七)注意事项
桥梁模式的意图还是对变化的封装,尽量把可能变化的因素封装到最、最小的逻辑单元中,避免风险扩散。如果在进行系统设计时,发现类的继承有N层时,可以考虑使用桥梁模式。
八)扩展
九)总结
我们来看看Corp生产Product的例子,因为Corp公司有可能生产不一样的产品Product,就是因为不知道将来要生产什么样的产品,所以把产品放出去(变成抽象类或者接口类),通过setter或者构造函数把产品Product类注入进来。
这种有两个好处:1)Corp类和Product类可以独立变化,就是解耦;2)Corp类把变化方法的放出去了,这样不会对Corp类产生影响;
如:Father类 -> Son类(Father子类) -> GrandSom类(Son子类)
桥梁模式描述了类间弱关联关系,Father类完全可以把可能会变化的方法放出去,Son子类要拥有这个方法很简单,桥梁搭过去,获得这个方法,GrandSon也一样,即使你Son子类不想使用这个方法也没关系,对GrandSon不产生影响,它不是从Son中继承来的方法。
对于比较明确不发生变化的,则通过继承来完成;若不能确定是否会发生变化的,那就认为是会发生变化, 则通过桥梁模式来解决。
二)定义
将抽象和实现解耦,使得两者可以独立地变化。
三)代码例子
共计四个类:1)实现化角色;2)具体实现化角色(可多个);3)抽象化角色;4)具体抽象化角色(可多个);
1)实现化角色
/**
* 实现化角色(产品类)
*
* @author levovo
*/
public abstract class AbsProduct {
public abstract void method1();
public abstract void method2();
}
2)具体实现化角色(可多个)
/**
* 具体实现化角色1(产品类1)
*
* @author levovo
*/
public class ConcreteProduct1 extends AbsProduct {
@Override
public void method1() {
System.out.println("ConcreteProduct1()->method1()");
}
@Override
public void method2() {
// 业务逻辑处理
System.out.println("ConcreteProduct1()->method2()");
}
}
/**
* 具体实现化角色2(产品类2)
*
* @author levovo
*/
public class ConcreteProduct2 extends AbsProduct {
@Override
public void method1() {
System.out.println("ConcreteProduct2()->method1()");
}
@Override
public void method2() {
// 业务逻辑处理
System.out.println("ConcreteProduct2()->method2()");
}
}
3)抽象化角色
/**
* 抽象化角色(公司类)
*
* @author levovo
*/
public abstract class AbsCorp {
protected AbsProduct product = null;
public AbsCorp(AbsProduct product) {
this.product = product;
}
// 产品类的公共方法
public void method1() {
System.out.println("AbsCorp()->method1()");
this.product.method1();
this.product.method2();
}
// 抽象方法
public abstract void method2();
}
4)具体抽象化角色(可多个)
/**
* 具体抽象化角色1(公司类1)
*
* @author levovo
*/
public class Corp1 extends AbsCorp {
public Corp1(AbsProduct product) {
super(product);
}
@Override
public void method2() {
System.out.println("Corp1()->method2()");
}
}
/**
* 具体抽象化角色2(公司类2)
*
* @author levovo
*/
public class Corp2 extends AbsCorp {
public Corp2(AbsProduct product) {
super(product);
}
@Override
public void method2() {
System.out.println("Corp2()->method2()");
}
}
场景使用例子:
/**
* 场景使用例子
*
* @author levovo
*/
public class Client {
public static void main(String[] args) {
// 产品
AbsProduct product = new ConcreteProduct1();
// AbsProduct product = new ConcreteProduct2();
// 公司,因公司不知道将来要生产什么样的产品,所以将产品放出去,
// 通过构造函数或者setter注入进来,那么在Corp类就可以使用Product的方法了。
AbsCorp corp = new Corp1(product);
// AbsCorp corp = new Corp2(product);
corp.method1();
corp.method2();
}
}
1)增加公司,要么继承Corp类,要么继承HouseCorp或ShanZhaiCorp,不用再修改原有的类了。
2)增加产品,继承Product类,或者继承House类,你要把房子分为公寓房,别墅,商业用房等。
你唯一要修改的就是Client类。类都增加了,高层模式也需要修改,也就是说Corp类和Product类都可以自由地扩展,而不会对整个应用产生太大的变更,这就是桥梁模式。
四)优点
1)抽象与实现分离
这也是桥梁模式的主要特点,它完全是为了解决继承的缺点而提出的设计模式,在该模式下,实现可以不受抽象的约束,不用再绑定在一个固定的抽象层次上。
2)优秀的扩充能力
看看我们的例子,想增加实现?没问题!想增加抽象,也没有问题!只要对外暴露的接口层允许这样的变化,我们已经把变化的可能性减到最小。
3)实现细节对客户透明
客户不用关心细节的实现,它已经由抽象层通过聚合关系完成了封装。
五)缺点
六)使用场景
1)不希望或不适用使用继承的场景
例如继承层次过渡,无法更细化设计颗粒等场景,需要考虑使用桥梁模式。
2)接口或抽象类不稳定的场景
明知道接口不稳定还想通过实现或继承来实现业务需求,那是得不偿失的,也是比较失败的做法。
3)重用性要求较高的场景
设计的颗粒度超细,则被重用的可能性就越大,而采用继承则受父类的限制,不可能出现太细的颗粒度。
七)注意事项
桥梁模式的意图还是对变化的封装,尽量把可能变化的因素封装到最、最小的逻辑单元中,避免风险扩散。如果在进行系统设计时,发现类的继承有N层时,可以考虑使用桥梁模式。
八)扩展
九)总结
我们来看看Corp生产Product的例子,因为Corp公司有可能生产不一样的产品Product,就是因为不知道将来要生产什么样的产品,所以把产品放出去(变成抽象类或者接口类),通过setter或者构造函数把产品Product类注入进来。
这种有两个好处:1)Corp类和Product类可以独立变化,就是解耦;2)Corp类把变化方法的放出去了,这样不会对Corp类产生影响;
如:Father类 -> Son类(Father子类) -> GrandSom类(Son子类)
桥梁模式描述了类间弱关联关系,Father类完全可以把可能会变化的方法放出去,Son子类要拥有这个方法很简单,桥梁搭过去,获得这个方法,GrandSon也一样,即使你Son子类不想使用这个方法也没关系,对GrandSon不产生影响,它不是从Son中继承来的方法。
对于比较明确不发生变化的,则通过继承来完成;若不能确定是否会发生变化的,那就认为是会发生变化, 则通过桥梁模式来解决。