一、桥接模式的介绍
1、定义
桥接模式是将抽象和实现解耦,使得两者可以独立的变化。这么介绍会有些抽象,所以用例子来说明:众所周知,手机我们可以打电话或者发短信,并且手机有很多的样式,如:直立式、折叠式的,而手机的品牌有很多种,如:华为、小米、oppo等等。如果现在要去实现这个需求,那么它的UML类图如下:
如果此时,又有一个新的类型:旋转式的手机,那么所有的手机品牌就需要再次增加对应的类。同样,如果我们新增一个Vivo手机,那么又需要在每个样式类下面去添加Vivo手机。这样不仅违反了单一职责原则,而且增加了大量的代码量。所以,就提出了桥接模式。
桥接模式中存在以下四个角色:
- 抽象化角色(Abstraction):该角色抽象化的给出定义,并保存一个对实现化对象的引用。
- 实现化角色(Implementor):该角色给出实现化角色的接口,但不给出具体的实现。
- 修正抽象化角色(RefinedAbstraction):该角色扩展抽象化角色,它引用实现化角色并对抽象化角色进行修正。
- 具体实现化角色(ConcreteImplementor):该角色对实现化角色接口中的方法进行具体实现。
桥接模式的UML图如下:
2、使用场景
- 当一个类存在两个独立变化的维度,且这两个维度都需要进行扩展时。
- 当一个系统不希望使用继承或因为多层次继承导致系统类的个数急剧增加时。
- 当一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性时。
3、优缺点
(1)优点
- 分离抽象接口及其实现部分。
- 提高了比继承更好的解决方案。桥接模式提高了系统的可扩充性,在两个变化维度中任意扩展一个维度,都不需要修改原有系统。
- 实现细节对客户透明,可以对用户隐藏实现细节。
(2)缺点
- 桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。
- 桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围具有一定的局限性
二、桥接模式的实现
以上述例子,来看一下UML类图:
实现过程如下:
定义一个实现化角色Brand:
/**
* 手机品牌
*/
public interface Brand {
void open();
void close();
void call();
}
定义两个具体实现化角色:HuaWei和xiaoMi:
public class Huawei implements Brand{
@Override
public void open() {
System.out.println("华为手机开机");
}
@Override
public void close() {
System.out.println("华为手机关机");
}
@Override
public void call() {
System.out.println("华为手机打电话");
}
}
public class XiaoMi implements Brand{
@Override
public void open() {
System.out.println("小米手机开机");
}
@Override
public void close() {
System.out.println("小米手机关机");
}
@Override
public void call() {
System.out.println("小米手机打电话");
}
}
定义一个抽象化角色Phone:
public abstract class Phone {
//品牌
private Brand brand;
public Phone(Brand brand) {
this.brand = brand;
}
//开机
protected void open(){
this.brand.open();
}
//打电话
protected void call(){
this.brand.call();
}
//关机
protected void close(){
this.brand.close();
}
}
定义修正抽象化角色:
/**
* 折叠手机
*/
public class FoldedPhone extends Phone{
public FoldedPhone(Brand brand) {
super(brand);
}
public void open(){
super.open();
System.out.println("折叠手机");
}
public void close(){
super.call();
System.out.println("折叠手机");
}
public void call(){
super.call();
System.out.println("折叠手机");
}
}
/**
* 直立手机
*/
public class UpRightPhone extends Phone{
public UpRightPhone(Brand brand) {
super(brand);
}
public void open(){
super.open();
System.out.println("直立手机");
}
public void close(){
super.call();
System.out.println("直立手机");
}
public void call(){
super.call();
System.out.println("直立手机");
}
}
测试类如下:
public class Client {
public static void main(String[] args) {
Phone phone1 = new FoldedPhone(new Huawei());
phone1.open();
phone1.call();
phone1.close();
System.out.println("===========");
Phone phone2 = new UpRightPhone(new XiaoMi());
phone2.open();
phone2.call();
phone2.close();
System.out.println("===========");
}
}