桥接模式(合成/聚合+单一职责的体现)

来源:互联网 发布:adhoc网络搭建 编辑:程序博客网 时间:2024/06/18 16:13

假设现在有这么一个请求:创建多个不同的窗口系统,如临时会话窗口(transientWindow)和图标窗口(iconWindow)以及其他各种类型窗口,同时这些窗口的要在linux和unix以及window上都能创建。这是一个典型的多种变化结合在一起的例子。很多人一开始会使用继承来解决这个问题,如下:

//定义一个窗口抽象类,里面包含了描绘窗口的抽象接口

public abstract window(){

public abstract void drawWindow();

//一个图标窗口

public abstract iconWindow () extends window{

}

//Unix下的图标窗口实现

public class UnixIconWindow extennd iconWindow(){

       public void drawWindow(){

   System.out.println("this is Unix IconWindow");

       }

}

//Linux下的图标窗口实现

public class LinuxIconWindow extennd iconWindow(){

       public void drawWindow(){

   System.out.println("this is Linux IconWindow");

       }

}

基本的功能已经完成,现在我们来看我们新的需求:假设我们要增加一个窗口,如应用窗口(ApplicationWindow),这时我们就不得不创建一个应用窗口类,继承抽象类window,

同时为了让它能在不同平台上都实现,就不得不创建两个子类,分别时LinuxAppliactionWindow和UnixAppliactionWindow,这种改动是非常巨大的。我们在设想一下,假如我们

又要让所有窗口能在windows上实现,那么就必须为每一个窗口类又创建一个Winodws...Window类。我们看到,每一个变化都会引起指数形式增长的变化。归根接底是因为继

承具有非常大的耦合性,而且当父类的接口不适用时,我们也没办法直接更改,否则会引起所有子类的变化。面对这种多种变化且相互影响的需求,我们考虑使用合成/聚合原则。

//窗口抽象类,定义得到一些列窗口的抽象操作
public abstract class Window {

        //实现窗口创建的具体对象
private WindowImpl windowImpl;

public void setWindowImpl(WindowImpl windowImpl){
this.windowImpl = windowImpl;
}

public WindowImpl getWindowImpl(){
return this.windowImpl;
}

//这里假设这两种基本操作可以绘制所有图形
public abstract void drawWindow();
}

//icon图标类

public class IconWindow extends Window{
@Override
public void drawWindow() {
System.out.println("icon图标窗口创建");

                 //将窗口的创建过程交给父类中的windowImpl实现,由于windowImpl的变量类型是一个接口,因此这里实现了窗口和系统的解耦
getWindowImpl().DevDrawWindow();  
}
}

//临时会话窗口类

public class TransientWindow extends Window{
@Override
public void drawWindow() {

System.out.println("临时会话窗口创建:");
getWindowImpl().DevDrawWindow();
}
}


//实现窗口创建的抽象接口

public interface WindowImpl {
public void DevDrawWindow();
}


//具体的窗口创建实现类,这里是在Unix系统下创建窗口

public class UnixWindowImpl implements WindowImpl {

@Override
public void DevDrawWindow() {
System.out.println("Unix window build success");
}
}

还可以类似的创建多个不同系统平台的具体的窗口创建实现类。

。。。。。。。。。。。

public class App {
public static void main(String[] args) {
Window window = new IconWindow();
window.setWindowImpl(new UnixWindowImpl());
window.drawWindow();
}
}

此时如果再要增加一个系统的话,只需要创建一个实现WindowImpl接口的具体实现类,增加一个窗口类型的话,也只要创建一个继承window抽象类的实现类就行。这就是把

变化分离。我们把上面的接口用uml图抽象出来,就是:



其实这就是桥接模式。桥接模式:将抽象部分和实现部分分离,使他们可以独立的变化。这里window类以及它的子类就是属于抽象层,因为他们不用关心具体的窗口创建过程

。windowImpl以及它的子类属于实现部分,他们负责具体的实现。通过组合,他们可以独立的变化而互不影响。

在面对多种变化且这些变化互相关联时,使用桥接模式往往能使代码更清晰,也更容易对程序进行扩展



1 0
原创粉丝点击