桥接模式是一种结构型设计模式,基于类的最小设计原则,通过使用封装、聚合及继承等行为让不同的类承担不同的职责。它的主要特点是把抽象(Abstraction)与行为实现(lmplementation)分离开来,从而可以保持各部分的独立性以及应对他们的功能扩展。
举个例子:市面上的手机分为普通手机,滑动手机,折叠手机。普通手机又根据品牌分为vivo普通手机、vivo滑动手机、vivo折叠手机······
用这张图表示,如果这里需要在加一种老年按键手机,是不是得从phone中来一类老年按键手机,然后又分为vivo,oppo,huawei。这样看来是不是每次来一个种类就要再写三个手机牌子,如果再来一个小米品牌每个种类都要加小米品牌,这就显得特别麻烦,扩展性特别不好。
那是不是可以把品牌分为一组,把手机类型分为一组,再去搭配连接,桥接模式就展现了此思想,话不多说直接上代码。
首先把品牌搞定,每个品牌都有自己的logo,因此开关机画面也就不一样对吧,先建一个brand接口
public interface Brand {
// 每个手机品牌都有自己的开机关机logo
public void openLogo();
public void closeLogo();
}
品牌有vivo、oppo,所以创建两个类并实现brand接口
public class Vivo implements Brand{
@Override
public void openLogo() {
System.out.println("开机:vivo");
}
@Override
public void closeLogo() {
System.out.println("关机:vivo");
}
}
public class Oppo implements Brand{
@Override
public void openLogo() {
System.out.println("开机:oppo");
}
@Override
public void closeLogo() {
System.out.println("关机:oppo");
}
}
品牌这一块ok了接下来是手机类型,创建一个抽象类phone,手机应该有自己的开关机logo画面,所以要跟刚刚创建的品牌做关联,使用聚合的方式。手机得有自己的开关机功能吧,所以声明两个抽象方法。
public abstract class Phone{
protected Brand brand;
public Phone(Brand brand) {
this.brand = brand;
}
public abstract void open();
public abstract void close();
}
创建一个FoldedPhone折叠手机类,并继承Phone类使它具有手机的功能(开关机),具体开关机要怎样的画面就在方法的实现做逻辑处理。
public class FoldedPhone extends Phone{
public FoldedPhone(Brand brand) {
super(brand);
}
@Override
public void open() {
brand.openLogo(); //用上手机品牌的Logo
System.out.println("折叠手机开机工作");
}
@Override
public void close() {
brand.closeLogo(); //用上手机品牌的Logo
System.out.println("折叠手机关机工作");
}
}
测试一下
public class Client {
public static void main(String[] args) {
Brand vivo = new Vivo();
Phone phone = new FoldedPhone(vivo);
phone.open();
System.out.println("=================");
phone.close();
/**
* 输出结果入下:
*
* 开机:vivo
* 折叠手机开机工作
* =================
* 关机:vivo
* 折叠手机关机工作
*/
}
}
目前的结构我简单的用类图表示一下
可以看出Phone是起到了桥梁作用,把Brand和FoldedPhone联系起来,这种方式扩展性就高了很多,如果要再加一个老年按键机,那么我只需要创建一个类继承Phone即可。
public class OlderAJPhone extends Phone{
public OlderAJPhone(Brand brand) {
super(brand);
}
@Override
public void open() {
brand.openLogo(); //用上手机品牌的Logo
System.out.println("老年按键手机开机工作");
}
@Override
public void close() {
brand.closeLogo(); //用上手机品牌的Logo
System.out.println("老年按键手机关机工作");
}
}
public class Client {
public static void main(String[] args) {
Brand vivo = new Vivo();
Phone phone = new FoldedPhone(vivo);
phone.open();
System.out.println("=================");
phone.close();
//如果要用vivo版老年按键机
OlderAJPhone olderAJPhone = new OlderAJPhone(new Vivo());
olderAJPhone.open();
//如果要用oppo版老年按键机
OlderAJPhone olderAJPhone2 = new OlderAJPhone(new Oppo());
olderAJPhone2.open();
}
}
同理,如果要再加一个小米品牌,只需要创建一个小米品牌类继承Brand接口,用的话就new 个小米对象。
桥接模式的引入虽然极大的提供了系统的灵活性,但是它也增加了对系统的理解和设计难度,需要分析出哪个是实现层哪个是抽象层。