桥接模式是什么
桥接模式是结构型模式,当系统中的某个类中存在两个或者以上的维度的变化,可以将每个维度分离出来,使得每个维度都可以进行独立扩展,符合单一职责的原则。将抽象部分与实现部分分离,使它们都可以独立的变化。桥接模式用一种巧妙的方式处理多层继承存在的问题,用抽象关联取代了传统的多层继承,将类之间的静态继承关系转换为动态的对象组合关系(看完下文内容自会理解),使得系统更加灵活,并易于扩展,同时有效控制了系统中类的个数。
桥接模式使用场景
1、如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过桥 接模式可以使它们在抽象层建立一个关联关系。 2、对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。 3、一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。
桥接模式优缺点
优点
1、抽象和实现的分离:我们将具有两个独立变化维度的类的一些普通业务方法和与之关系最密切的维度设计为“抽象类”层次结构(抽象部分),而将另一个维度设计为“实现类”层次结构(实现部分)
2、优秀的扩展能力:实现层和抽象层互不影响,只需要增加对应层的抽象类或者实现类,无需修改代码,且不会导致类增长过快。
3、实现细节对客户透明。
缺点
桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。
辅助图示
如上图所示,将两个不同的维度拆分为抽象部分和实现部分。各自可以后续扩展自己的部分的类。
示例代码
1、实现部分的接口(Lettering)及其实现类
public interface Lettering { void doLettering(); }
public class Italics implements Lettering{ @Override public void doLettering() { System.out.println("纹刻斜体字字体。"); } }
public class RegularScript implements Lettering{ @Override public void doLettering() { System.out.println("纹刻楷书字体。"); } }
public class SongTypeFace implements Lettering{ @Override public void doLettering() { System.out.println("纹刻宋体字体。"); } }
2、抽象部分的抽象类(Clouthes)以及其子类
public abstract class Clothes { protected Lettering lettering; //定义实现类接口对象 public Clothes(Lettering lettering) { this.lettering = lettering; } public abstract void doProduceClothes(); //声明抽象业务方法 }
public class Nike extends Clothes{ public Nike(Lettering lettering) { super(lettering); } @Override public void doProduceClothes() { System.out.println("生产阿迪达斯服饰。"); //业务代码 lettering.doLettering(); //调用实现类的方法 //do something (业务代码) } }
public class Nike extends Clothes{ public Nike(Lettering lettering) { super(lettering); } @Override public void doProduceClothes() { System.out.println("生产耐克服饰。");//业务代码 lettering.doLettering();//调用实现类的方法 //do something (业务代码) } }
3、Client
对于客户端而言,可以针对两个维度的抽象层编程,在程序运行时再动态确定两个维度的子类,动态组合对象,将两个独立变化的维度完全解耦,以便能够灵活地扩充任一维度而对另一维度不造成任何影响。
public class TestClient { public static void main(String[] args) { Clothes adidasSongTypeFaceClouth = new Adidas(new SongTypeFace()); Clothes adidasRegularScriptClouth = new Adidas(new RegularScript()); Clothes adidasItalicsClouth = new Adidas(new Italics()); Clothes nikeSongTypeFaceClouth = new Nike(new SongTypeFace()); adidasSongTypeFaceClouth.doProduceClothes(); System.out.println("----------------------"); adidasRegularScriptClouth.doProduceClothes(); System.out.println("----------------------"); adidasItalicsClouth.doProduceClothes(); System.out.println("----------------------"); nikeSongTypeFaceClouth.doProduceClothes(); } }
运行结果
生产阿迪达斯服饰。 纹刻宋体字体。 ---------------------- 生产阿迪达斯服饰。 纹刻楷书字体。 ---------------------- 生产阿迪达斯服饰。 纹刻斜体字字体。 ---------------------- 生产耐克服饰。 纹刻宋体字体。