JAVA设计模式(19) —桥接(Bridge)模式
2013-01-08 14:59
441 查看
定义:将抽象部分与它的实现部分分离,使它们可以独立的变化。
类型:对象结构型模式
类图:
桥接模式的结构
Abstraction :抽象类的接口,维护一个指向Implementor类型对象的指针,在本例中为 IPluginPlatform。
RefinedAbstraction :扩充Abstraction定义的接口,在本例中为 PluginVersionA、PluginVersionB。
Implementor :定义实现类的接口,该接口不一定要与Abstraction 完全一致;事实上,这两个接口可以完全不同。一般来讲 Implementor 接口仅提供基本操作,而Abstraction 则定义了基于这些基本操作的较高层次的操作。
ConcreteImplementor :实现Implementor 并定义它的具体实现。
示例
假设要为一个系统设计插件,首先这个系统是需要跨平台的,其次,由于插件经常会版本升级,所以系统需要支持多多个版本插件。顺着需求,我们可能会这样去考虑解决方案。
因为需要跨平台,那么通过抽象和继承来实现跨平台。
[align=left]
[/align]
[align=left]又因为每个平台都需要支持多个插件版本,那就继续在每个平台下扩展不同版本吧。
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]代码如下:[/align]
[align=left]
[/align]
这里省略 windows以外平台, 以及 Ver1,2以外版本的代码。
以上确实是一种解决方法,但却不是一种好方法。试想一下如果现在又多出一种平台了怎么办?只能再加一个继承分支,同时对这个平台也需要追加多个版本的实现。而如果又升级了一个版本怎么办?只能在每种平台下都追加该版本的实现。类结构就膨胀成如下这样:
现在可以看出,平台和版本这系统中两个层次的实现被耦合在一起,导致每次功能追加都伴随着重复的实现和类的膨胀。很难想象,当再追加 n个平台,和 n个版本的支持后,系统结构会爆炸式的膨胀成什么样!伴随着的还有设计,编码,测试等成本以及风险的成倍增加。
Bridge模式实现代码
桥接模式适用场景
你不希望在抽象和它的实现部分之间有一个固定的绑定关系。
类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充。
对一个抽象的实现部分的修改应对客户不产生影响,即客户端的代码不必重新编译。
(C++)你想对客户完全隐藏抽象的实现部分。
你想在多个实现间 共享实现,但同时要求客户并不知道这一点。
桥接模式的优点
分离接口及其实现部分。一个实现未必不变地邦定在一个接口上。抽象类的实现可以在运行的时刻进行配置,一个对象甚至可以在运行的时候改变它的实现。
将Abstraction和Implementor分离有助于降低对实现部分编译时刻的依赖性,当改变一个实现类时,并不需要重新编译Abstraction类和它的客户程序。为了保证一个类库的不同版本之间的二进制兼容性,一定要有这个性质。
另外接口与实现分离有助于分层,从而产生更好的结构化系统,系统的高层部分仅需知道Abstraction和Implementor即可。
提高可扩充性。你可以独立地对Abstraction和Implementor层次结构进行扩充。
实现细节对客户的透明。你可以对客户隐藏实现细节。
类型:对象结构型模式
类图:
桥接模式的结构
Abstraction :抽象类的接口,维护一个指向Implementor类型对象的指针,在本例中为 IPluginPlatform。
RefinedAbstraction :扩充Abstraction定义的接口,在本例中为 PluginVersionA、PluginVersionB。
Implementor :定义实现类的接口,该接口不一定要与Abstraction 完全一致;事实上,这两个接口可以完全不同。一般来讲 Implementor 接口仅提供基本操作,而Abstraction 则定义了基于这些基本操作的较高层次的操作。
ConcreteImplementor :实现Implementor 并定义它的具体实现。
示例
假设要为一个系统设计插件,首先这个系统是需要跨平台的,其次,由于插件经常会版本升级,所以系统需要支持多多个版本插件。顺着需求,我们可能会这样去考虑解决方案。
因为需要跨平台,那么通过抽象和继承来实现跨平台。
[align=left]
[/align]
[align=left]又因为每个平台都需要支持多个插件版本,那就继续在每个平台下扩展不同版本吧。
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]代码如下:[/align]
abstract class IPlugin { public abstract void loadPlugin(); public abstract void unloadPlugin(); public void start() { // add operation } public void stop() { // add operation } } class WindowsPlugin extends IPlugin { @Override public void loadPlugin() { } @Override public void unloadPlugin() { } } class WinPluginVer1 extends WindowsPlugin { @Override public void start() { loadPlugin(); super.start(); } @Override public void stop() { unloadPlugin(); super.stop(); } } class WinPluginVer2 extends WindowsPlugin { @Override public void start() { loadPlugin(); super.start(); } @Override public void stop() { unloadPlugin(); super.stop(); } }
[align=left]
[/align]
这里省略 windows以外平台, 以及 Ver1,2以外版本的代码。
以上确实是一种解决方法,但却不是一种好方法。试想一下如果现在又多出一种平台了怎么办?只能再加一个继承分支,同时对这个平台也需要追加多个版本的实现。而如果又升级了一个版本怎么办?只能在每种平台下都追加该版本的实现。类结构就膨胀成如下这样:
现在可以看出,平台和版本这系统中两个层次的实现被耦合在一起,导致每次功能追加都伴随着重复的实现和类的膨胀。很难想象,当再追加 n个平台,和 n个版本的支持后,系统结构会爆炸式的膨胀成什么样!伴随着的还有设计,编码,测试等成本以及风险的成倍增加。
Bridge模式实现代码
//抽象类接口 --> 插件 abstract class IPlugin{ protected IPluginPlatform platform; public void setPlatform(IPluginPlatform platform) { this.platform = platform; } public abstract void start(); public abstract void stop(); } //不同 版本号 实现 class PluginVersionA extends IPlugin{ @Override public void start() { platform.loadPlugin(); } @Override public void stop() { platform.unloadPlugin(); } } class PluginVersionB extends IPlugin{ @Override public void start() { platform.loadPlugin(); } @Override public void stop() { platform.unloadPlugin(); } } //抽象类接口 --> 平台 abstract class IPluginPlatform{ public abstract void loadPlugin(); public abstract void unloadPlugin(); } //Windows平台实现 class WindowsPlugin extends IPluginPlatform{ @Override public void loadPlugin() { System.out.println("WindowsPlugin loading ..."); } @Override public void unloadPlugin() { System.out.println("WindowsPlugin unLoading ..."); } } class LinuxPlugin extends IPluginPlatform{ @Override public void loadPlugin() { System.out.println("LinuxPlugin loading ..."); } @Override public void unloadPlugin() { System.out.println("LinuxPlugin unLoading ..."); } } //客户端调用 public class BridgeClient { /** * @param args */ public static void main(String[] args) { IPlugin plugin = new PluginVersionA(); IPluginPlatform platform = new WindowsPlugin(); plugin.setPlatform(platform); plugin.start(); plugin.stop(); } }
桥接模式适用场景
你不希望在抽象和它的实现部分之间有一个固定的绑定关系。
类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充。
对一个抽象的实现部分的修改应对客户不产生影响,即客户端的代码不必重新编译。
(C++)你想对客户完全隐藏抽象的实现部分。
你想在多个实现间 共享实现,但同时要求客户并不知道这一点。
桥接模式的优点
分离接口及其实现部分。一个实现未必不变地邦定在一个接口上。抽象类的实现可以在运行的时刻进行配置,一个对象甚至可以在运行的时候改变它的实现。
将Abstraction和Implementor分离有助于降低对实现部分编译时刻的依赖性,当改变一个实现类时,并不需要重新编译Abstraction类和它的客户程序。为了保证一个类库的不同版本之间的二进制兼容性,一定要有这个性质。
另外接口与实现分离有助于分层,从而产生更好的结构化系统,系统的高层部分仅需知道Abstraction和Implementor即可。
提高可扩充性。你可以独立地对Abstraction和Implementor层次结构进行扩充。
实现细节对客户的透明。你可以对客户隐藏实现细节。
相关文章推荐
- Java经典设计模式-结构型模式-桥接模式(Bridge)
- Java设计模式之从[暗黑破坏神"装备镶嵌宝石系统"]分析桥接(Bridge)模式
- JAVA设计模式之 桥接模式【Bridge Pattern】
- Java设计模式之结构型模式-桥接模式(Bridge)
- java设计模式之桥接模式(Bridge)
- java23种设计模式--桥接模式(bridge)
- 设计模式学习笔记---桥接模式bridge(Java版)
- JAVA设计模式(07):结构型-桥接模式(Bridge)
- Java开发中的23种设计模式详解----桥接模式(Bridge)
- Java语言设计模式之桥接(Bridge)模式
- Java设计模式——Bridge(桥接)模式
- Java设计模式-----Bridge桥接模式
- (10)Java设计模式-桥接模式(Bridge)
- Java设计模式(八):桥接模式bridge
- Java设计模式-----Bridge桥接模式
- Java设计模式之桥接模式(Bridge)
- 设计模式(七)----- 桥接模式(Bridge)----(JAVA版)
- Java设计模式-桥接模式(Bridge)
- Java23种设计模式案例:桥接模式(bridge)
- Java设计模式(三)Adapter(适配器),Bridge(桥接)