桥接模式
桥接模式,主要特点就是实现和抽象的分离,不只是简单的实现类实现抽象的功能,这样一来,无论是实现类扩展,还是抽象的扩展,都可以很方便的进行。通过使用封装、聚合及继承等行为让不同的类承担不同的职责。
这么说还是太抽象了,简单来讲,就是一个类的功能,有两个维度来控制,两个维度都有不同的实现,可以进行随意的组合。
举个栗子:我们出门旅游,可以去北京,可以去湖北,出行方式可以使开车,坐火车和坐飞机。关于出门这件事,就有2 x 3六种可能,如果按照老的方式,我们要写6个出行的类,按需调用在加上一个地点的接口,一个出行方式的抽象类,就是8个类,但是分开之后,我们只用写一个接口,一个抽象类,2个地点实现,3种出行实现,一共7个了,假若要去上海,那么还得加上3个不同方式去上海的类,而桥接模糊只需要加一个地点实现。还是看代码:
/**
* @author: hx
* @Time: 2019/5/16
* @Description: Place
*/
public interface Place {
void province();
}
/**
* @author: hx
* @Time: 2019/5/16
* @Description: Hubei
*/
public class Hubei implements Place {
@Override
public void province() {
System.out.println("去湖北省");
}
}
/**
* @author: hx
* @Time: 2019/5/16
* @Description: Beijing
*/
public class Beijing implements Place {
@Override
public void province() {
System.out.println("去北京市");
}
}
/**
* @author: hx
* @Time: 2019/5/16
* @Description: Vehicle
*/
public abstract class Vehicle {
private Place mPlace;
public Place getPlace() {
return mPlace;
}
public void setPlace(Place place) {
mPlace = place;
}
public abstract void GoOut();
}
/**
* @author: hx
* @Time: 2019/5/16
* @Description: Car
*/
public class Car extends Vehicle {
@Override
public void GoOut() {
System.out.println("开车出门");
getPlace().province();
}
}
/**
* @author: hx
* @Time: 2019/5/16
* @Description: Train
*/
public class Train extends Vehicle {
@Override
public void GoOut() {
System.out.println("坐火车");
getPlace().province();
}
}
/**
* @author: hx
* @Time: 2019/5/16
* @Description: Plane
*/
public class Plane extends Vehicle {
@Override
public void GoOut() {
System.out.println("坐飞机");
getPlace().province();
}
}
搭配一下出游
public static void main(String[] args){
Vehicle car = new Car();
Vehicle train = new Train();
Vehicle plane = new Plane();
Place hubei = new Hubei();
Place beijing = new Beijing();
car.setPlace(hubei);
car.GoOut();
car.setPlace(beijing);
car.GoOut();
train.setPlace(hubei);
train.GoOut();
train.setPlace(beijing);
train.GoOut();
plane.setPlace(hubei);
plane.GoOut();
plane.setPlace(beijing);
plane.GoOut();
}
输出结果:
开车出门
去湖北省
开车出门
去北京市
坐火车
去湖北省
坐火车
去北京市
坐飞机
去湖北省
坐飞机
去北京市
当我们要增加一个地点上海时:
/**
* @author: hx
* @Time: 2019/5/16
* @Description: Shanghai
*/
public class Shanghai implements Place {
@Override
public void province() {
System.out.println("去上海");
}
}
只需要这一个实现
当我们要加一种出行方式时:
/**
* @author: hx
* @Time: 2019/5/16
* @Description: Ship
*/
public class Ship extends Vehicle {
@Override
public void GoOut() {
System.out.println("坐船");
getPlace().province();
}
}
也只需要增加一个是实现。
总结:
1.优点
(1)实现了抽象和实现部分的分离
桥接模式分离了抽象部分和实现部分,从而极大的提供了系统的灵活性,让抽象部分和实现部分独立开来,分别定义接口,这有助于系统进行分层设计,从而产生更好的结构化系统。对于系统的高层部分,只需要知道抽象部分和实现部分的接口就可以了。
(2)更好的可扩展性
由于桥接模式把抽象部分和实现部分分离了,从而分别定义接口,这就使得抽象部分和实现部分可以分别独立扩展,而不会相互影响,大大的提供了系统的可扩展性。
(3)可动态的切换实现
由于桥接模式实现了抽象和实现的分离,所以在实现桥接模式时,就可以实现动态的选择和使用具体的实现。
(4)实现细节对客户端透明,可以对用户隐藏实现细节。
2.缺点
(1)桥接模式的引入增加了系统的理解和设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计和编程。
(2)桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围有一定的局限性。
3.使用场景
(1)如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系。
(2)抽象化角色和实现化角色可以以继承的方式独立扩展而互不影响,在程序运行时可以动态将一个抽象化子类的对象和一个实现化子类的对象进行组合,即系统需要对抽象化角色和实现化角色进行动态耦合。
(3)一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。
(4)虽然在系统中使用继承是没有问题的,但是由于抽象化角色和具体化角色需要独立变化,设计要求需要独立管理这两者。
(5)对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用