桥接模式(Bridge)
桥接模式也称为桥梁模式、接口模式或者柄体(Handle and Body)模式,是将抽象部分与他的具体实现部分分离,使它们都可以独立地变化,通过组合的方式建立两个类之间的联系,而不是继承。
简单理解的话:可以想象成通过一个桥梁把两个原本属于继承关系的类,给他改为了组合关系,变得更灵活。
什么情况适合用桥接模式:
在继承关系的基础上又需要灵活多变的两个和两个以上的子类,那么就可以用桥接模式,利用组合达到灵活多变的效果。
角色
桥接(Bridge)模式包含以下主要角色:
- 抽象化(Abstraction)角色 :定义抽象类,并包含一个对实现化对象的引用。
- 扩展抽象化(Refined Abstraction)角色 :是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法。
- 实现化(Implementor)角色 :定义实现化角色的接口,供扩展抽象化角色调用。
- 具体实现化(Concrete Implementor)角色 :给出实现化角色接口的具体实现。
示例代码
不用桥接模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| public interface Brand { void info(); }
public class Dell implements Brand { @Override public void info() { System.out.print("戴尔电脑"); } }
public class Lenovo implements Brand { @Override public void info() { System.out.println("联想电脑"); } }
public class DellDesktop extends Dell { @Override public void info() { super.info(); System.out.println("台式机"); } }
public class DellNoteBook extends Dell{ @Override public void info() { super.info(); System.out.println("笔记本"); } }
public class Main { public static void main(String[] args) { Brand dellDesktop = new DellDesktop(); dellDesktop.info(); Brand dellNoteBook = new DellNoteBook(); dellNoteBook.info();
} }
|
其他品牌的我就不写了,如果我们按照这样去写的话,2*3=6要多写6个类,如果我们后续又要增强新品牌,是不是又要写这些重复的类呢
用桥接模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
| public interface Brand { void info(); }
public class Dell implements Brand { @Override public void info() { System.out.print("戴尔电脑"); } }
public class Lenovo implements Brand { @Override public void info() { System.out.println("联想电脑"); } }
public abstract class Computer { private Brand brand;
public Computer(Brand brand) { this.brand = brand; } public void info(){ brand.info(); } }
public class Desktop extends Computer { public Desktop(Brand brand) { super(brand); }
@Override public void info() { super.info(); System.out.println("台式机"); } }
public class NoteBook extends Computer { public NoteBook(Brand brand) { super(brand); } @Override public void info() { super.info(); System.out.println("笔记本"); } }
public class Main { public static void main(String[] args) { Computer dellDesktop = new Desktop(new Dell()); dellDesktop.info(); Computer dellNoteBook = new NoteBook(new Dell()); dellNoteBook.info(); Computer Lenovo = new Desktop(new Lenovo()); Lenovo.info(); Computer Lenovo1 = new NoteBook(new Lenovo()); Lenovo1.info(); } }
|
这样是不是就可以减少了很多类呢?同时更加灵活。
另外一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| public interface Video { void decode(String fileName); }
public class Mp4 implements Video{ @Override public void decode(String fileName) { System.out.println("MP4视频文件:"+ fileName); } }
public class Rmvb implements Video{ @Override public void decode(String fileName) { System.out.println("rmvb文件:" + fileName); } }
@AllArgsConstructor public abstract class OperatingSystem { Video video; public abstract void play(String fileName); }
public class Ios extends OperatingSystem { public Ios(Video video){ super(video); } @Override public void play(String fileName) { video.decode(fileName); } }
public class Windows extends OperatingSystem { public Windows(Video video){ super(video); } @Override public void play(String fileName) { video.decode(fileName); } }
|
总结
适用场景:
- 在抽象和具体实现之间需要增加更多的灵活性的场景。
- 一个类存在两个(或多个)独立变化的维度,而这两个(或多个)维度都需要独立进行扩展。
- 不希望使用继承,或因为多层继承导致系统类的个数剧增。
优点:
- 分离抽象部分及其具体实现部分。
- 提高了系统的扩展性。
- 符合开闭原型。
- 符合合成复用原则。
缺点:
- 增加了系统的理解与设计难度。
- 需要正确地识别系统中两个独立变化的维度。