您的位置:首页 > 编程语言 > Java开发

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]




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层次结构进行扩充。
实现细节对客户的透明。你可以对客户隐藏实现细节。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: