只必要提供3种型号的毛笔,and Body)方式或接口(Interface)形式

**【学习难度:★★★☆☆,使用频率:★★★☆☆】 **

【学习难度:★★★☆☆,使用功效:★★★☆☆】
直白出处:http://woquanke.com/books/gof/
梳理和读书:https://github.com/BruceOuyang/boy-design-pattern
简书日期: 2018/03/09
简书首页:https://www.jianshu.com/p/0fb891a7c5ed

定义

  桥接方式(Bridge
Pattern):将抽象部分与它的兑现部分分离,使它们都可以单身地转移。它是一种对象结构型方式,又叫做柄体(Handle
and Body)形式或接口(Interface)方式。

作用:桥接形式用一种高超的方法处理多层继承存在的难点,用空洞关联代替了观念的多层继承,将类之间的静态继承关系转移为动态的对象组合关系,使得系统越来越灵活,并简单扩充,同时有效控制了系统中类的个数。

拍卖多维度变化

拍卖多维度变迁——桥接形式(一)

结构图

图片 1

要素:

  • Abstraction(抽象类):用于定义抽象类的接口,它一般是抽象类而不是接口,其中定义了3个Implementor(完成类接口)类型的对象并得以保养该对象,它与Implementor之间具有关联关系,它既可以涵盖抽象业务方法,也足以蕴含具体业务方法。
  • RefinedAbstraction(扩充抽象类):扩展由Abstraction定义的接口,经常意况下它不再是抽象类而是具体类,它达成了在Abstraction中注脚的悬空业务方法,在RefinedAbstraction中可以调用在Implementor中定义的事务方法。
  • Implementor(落成类接口):定义落成类的接口,那些接口不肯定要与Abstraction的接口完全一致,事实上那多少个接口可以完全两样,一般而言,Implementor接口仅提供基本操作,而Abstraction定义的接口大概会做愈来愈多更扑朔迷离的操作。Implementor接口对这几个基本操作进行了声称,而现实贯彻交给其子类。通过关系关系,在Abstraction中不仅仅抱有自个儿的章程,还能调用到Implementor中定义的措施,使用关联关系来替代继承关系。
  • ConcreteImplementor(具体贯彻类):具体落到实处Implementor接口,在区其他ConcreteImplementor中提供基本操作的差别达成,在程序运转时,ConcreteImplementor对象将替换其父类对象,提需求抽象类具体的工作操作方法。

在正儿八经介绍桥接方式以前,作者先跟大家座谈二种常见文具的界别,它们是毛笔和蜡笔。如若大家须要大中小3种型号的画笔,可以绘制12种差其他颜色,若是利用蜡笔,必要忧盛危明3×12

36支,但假如应用毛笔的话,只须求提供3种型号的毛笔,外加拾1个颜色盒即可,涉及到的对象个数仅为 3

  • 12 =
    15,远低于36,却能兑现与36支蜡笔同样的效果。若是扩张一种新型号的画笔,并且也亟需有所12种颜色,对应的蜡笔需追加12支,而毛笔只需增加一支。为何会这么呢?通过分析大家得以识破:在蜡笔中,颜色和型号三个不一样的变动维度(即八个不等的更动原因)融合在一道,无论是对颜色举行扩展照旧对型号举办扩大都势必会影响另一个维度;但在毛笔中,颜色和型号完成了分手,扩大新的水彩照旧型号对另一方都未曾其他影响。假诺采用软件工程中的术语,大家可以认为在蜡笔中颜色和型号之间存在较强的耦合性,而毛笔很好地将多头解耦,使用起来分外灵活,扩大也愈来愈便利。在软件开发中,大家也提供了一种设计情势来拍卖与画笔类似的全部多变化维度的事态,即本章将要介绍的桥接方式。

在正儿八经介绍桥接情势以前,小编先跟大家琢磨三种常见文具的区分,它们是毛笔和蜡笔。假如大家需求大中小3种型号的画笔,可以绘制12种分化的水彩,假如利用蜡笔,要求准备3×12

36支,但万一采纳毛笔的话,只必要提供3种型号的毛笔,外加十三个颜色盒即可,涉及到的靶子个数仅为
3 + 12 =
15,远低于36,却能促成与36支蜡笔同样的功力。假若增添一种新型号的画笔,并且也须求具备12种颜色,对应的蜡笔需增加12支,而毛笔只需增添一支。为啥会如此啊?通过分析我们可以得知:在蜡笔中,颜色和型号七个不等的转移维度(即八个不等的生成原因)融合在一块,无论是对颜色进行增加依旧对型号举办扩展都势必会影响另三个维度;但在毛笔中,颜色和型号完毕了分别,扩充新的水彩依然型号对另一方都不曾其他影响。如若使用软件工程中的术语,大家得以认为在蜡笔中颜色和型号之间存在较强的耦合性,而毛笔很好地将两端解耦,使用起来相当灵活,增加也更是方便。在软件开发中,大家也提供了一种设计格局来处理与画笔类似的兼具多变化维度的情景,即本章将要介绍的桥接情势。

10.1 跨平台图像浏览系统

萨妮软件集团欲开发三个跨平台图像浏览系统,须要该系统可以展现BMP、JPG、GIF、PNG等多样格式的文书,并且可以在Windows、Linux、Unix等两个操作系统上运维。系统第二将各类格式的公文分析为像素矩阵(Matrix),然后将像素矩阵展现在屏幕上,在分歧的操作系统中得以调用不一样的绘图函数来绘制像素矩阵。系统需具有较好的扩大性以支撑新的文件格式和操作系统。

Sunny软件商店的开发人士针对上述须要,提议了三个开首设计方案,其大旨构造如图10-1所示:

图片 2

图 10-1 跨平台图像浏览系统先导设计方案

在图10-1的起来设计方案中,使用了一种多层继承结构,Image是抽象父类,而每一种类型的图像类,如BMPImage、JPGImage等作为其一直子类,分裂的图像文件格式具有区其他分析方法,可以得到差别的像素矩阵;由于各个图像又须求在差别的操作系统中显得,区其余操作系统在屏幕上出示像素矩阵有所出入,由此要求为差别的图像类再提供一组在分化操作系统突显的子类,如为BMPImage提供八个子类BMPWindowsImp、BMPLinuxImp和BMPUnixImp,分别用于在Windows、Linux和Unix多个不一致的操作系统下显得图像。

我们后天对该设计方案举行辨析,发现存在如下几个第2难题:

(1)由于接纳了多层继承结构,导致系统中类的个数急剧扩张,图10-1中,在各个图像的操作系统完毕层提供了拾贰个具体类,加上各级抽象层的类,系统中类的总个数达到了拾八个,在该设计方案中,具体层的类的个数
= 所支撑的图像文件格式数×所支撑的操作系统数。

(2)系统扩大麻烦,由于每三个有血有肉类既包罗图像文件格式新闻,又包罗操作系统消息,因而无论是增添新的图像文件格式如故增添新的操作系统,都急需充实大气的具体类,例如在图10-1中追加一种新的图像文件格式TIF,则需求追加一个实际类来促成该格式图像在3种不一样操作系统的来得;假设扩展3个新的操作系统Mac
OS,为了在该操作系统下可以呈现种种类型的图像,要求增添陆个具体类。那将导致系统变得那多少个庞大,增添运转和护卫开支。

什么消除那三个难题?大家通过分析可查出,该种类设有八个单身变化的维度:图像文件格式和操作系统,如图10-2所示:

图片 3

图 10-2 跨平台图像浏览器中设有的多个独立变化维度示意图

在图10-2中,怎样将各样差距类型的图像文件解析为像素矩阵与图像文件格式自个儿有关,而什么在显示器上彰显像素矩阵则仅与操作系统相关。正因为图10-1所示结构将这二种任务集中在一个类中,导致系统增添麻烦,从类的计划角度解析,具体类BMPWindowsImp、BMPLinuxImp和BMPUnixImp等违反了“单一职责规范”,因为不断一个唤起它们变化的原故,它们将图像文件解析和像素矩阵突显那三种截然两样的天职融合在一起,任意二个任务暴发改变都须要修改它们,系统增添困难。

何以改革?我们的方案是将图像文件格式(对应图像格式的剖析)与操作系统(对应像素矩阵的彰显)多少个维度分离,使得它们可以独立变化,增加新的图像文件格式或然操作系统时都对另贰个维度不造成其余影响。看到那里,大家兴许会问,到底什么样在软件中落实将三个维度分离呢?不用着急,本章小编将为大家详细介绍一种用于拍卖多维度变迁的设计情势——桥接方式。

示例

  Sunny软件公司欲开发二个跨平台图像浏览系统,须求该系统可以突显BMP、JPG、GIF、PNG等三种格式的文书,并且可以在Windows、Linux、Unix等七个操作系统上运营。系统第二将种种格式的公文分析为像素矩阵(Matrix),然后将像素矩阵展现在屏幕上,在差别的操作系统中得以调用分歧的绘图函数来绘制像素矩阵。系统需具有较好的伸张性以支撑新的文件格式和操作系统。

图片 4

存在七个重大难题:
(1)由于应用了多层继承结构,导致系统中类的个数急剧扩张,具体层的类的个数
= 所帮助的图像文件格式数×所支撑的操作系统数。
(2)系统增添麻烦,由于每一个切实可行类既涵盖图像文件格式音信,又带有操作系统消息,由此不论扩充新的图像文件格式照旧扩大新的操作系统,都急需追加大气的具体类。

图片 5

难题所在:将多维度融合在一齐,违反了“单一任务规范”
消除方案:将多维度分别,独立变化

图片 6

//像素矩阵类:辅助类,各种格式的文件最终都被转化为像素矩阵,不同的操作系统提供不同的方式显示像素矩阵  
class Matrix {  
    //此处代码省略  
}  

//抽象图像类:抽象类  
abstract class Image {  
    protected ImageImp imp;  

    public void setImageImp(ImageImp imp) {  
        this.imp = imp;  
    }   

    public abstract void parseFile(String fileName);  
}  

//抽象操作系统实现类:实现类接口  
interface ImageImp {  
    public void doPaint(Matrix m);  //显示像素矩阵m  
}   

//Windows操作系统实现类:具体实现类  
class WindowsImp implements ImageImp {  
    public void doPaint(Matrix m) {  
        //调用Windows系统的绘制函数绘制像素矩阵  
        System.out.print("在Windows操作系统中显示图像:");  
    }  
}  

//Linux操作系统实现类:具体实现类  
class LinuxImp implements ImageImp {  
    public void doPaint(Matrix m) {  
        //调用Linux系统的绘制函数绘制像素矩阵  
        System.out.print("在Linux操作系统中显示图像:");  
    }  
}  

//Unix操作系统实现类:具体实现类  
class UnixImp implements ImageImp {  
    public void doPaint(Matrix m) {  
        //调用Unix系统的绘制函数绘制像素矩阵  
        System.out.print("在Unix操作系统中显示图像:");  
    }  
}  

//JPG格式图像:扩充抽象类  
class JPGImage extends Image {  
    public void parseFile(String fileName) {  
        //模拟解析JPG文件并获得一个像素矩阵对象m;  
        Matrix m = new Matrix();   
        imp.doPaint(m);  
        System.out.println(fileName + ",格式为JPG。");  
    }  
}  

//PNG格式图像:扩充抽象类  
class PNGImage extends Image {  
    public void parseFile(String fileName) {  
        //模拟解析PNG文件并获得一个像素矩阵对象m;  
        Matrix m = new Matrix();   
        imp.doPaint(m);  
        System.out.println(fileName + ",格式为PNG。");  
    }  
}  

//BMP格式图像:扩充抽象类  
class BMPImage extends Image {  
    public void parseFile(String fileName) {  
        //模拟解析BMP文件并获得一个像素矩阵对象m;  
        Matrix m = new Matrix();   
        imp.doPaint(m);  
        System.out.println(fileName + ",格式为BMP。");  
    }  
}  

//GIF格式图像:扩充抽象类  
class GIFImage extends Image {  
    public void parseFile(String fileName) {  
        //模拟解析GIF文件并获得一个像素矩阵对象m;  
        Matrix m = new Matrix();   
        imp.doPaint(m);  
        System.out.println(fileName + ",格式为GIF。");  
    }  
}  

<?xml version="1.0"?>  
<config>  
    <!--RefinedAbstraction-->  
    <className>JPGImage</className>   
    <!--ConcreteImplementor-->  
    <className>WindowsImp</className>  
</config>  

import javax.xml.parsers.*;  
import org.w3c.dom.*;  
import org.xml.sax.SAXException;  
import java.io.*;  
public class XMLUtil {  
//该方法用于从XML配置文件中提取具体类类名,并返回一个实例对象  
    public static Object getBean(String args) {  
        try {  
            //创建文档对象  
            DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();  
            DocumentBuilder builder = dFactory.newDocumentBuilder();  
            Document doc;                             
            doc = builder.parse(new File("config.xml"));   
            NodeList nl=null;  
            Node classNode=null;  
            String cName=null;  
            nl = doc.getElementsByTagName("className");  

            if(args.equals("image")) {  
                //获取第一个包含类名的节点,即扩充抽象类  
                classNode=nl.item(0).getFirstChild();  

            }  
            else if(args.equals("os")) {  
               //获取第二个包含类名的节点,即具体实现类  
                classNode=nl.item(1).getFirstChild();  
            }  

             cName=classNode.getNodeValue();  
             //通过类名生成实例对象并将其返回  
             Class c=Class.forName(cName);  
             Object obj=c.newInstance();  
             return obj;          
           }     
           catch(Exception e) {  
              e.printStackTrace();  
              return null;  
          }  
     }  
} 

class Client {  
    public static void main(String args[]) {  
        Image image;  
        ImageImp imp;  
        image = (Image)XMLUtil.getBean("image");  
        imp = (ImageImp)XMLUtil.getBean("os");  
        image.setImageImp(imp);  
        image.parseFile("小龙女");  
    }  
}  

10.1 跨平台图像浏览系统

      Sunny软件公司欲开发一个跨平台图像浏览系统,要求该系统能够显示BMP、JPG、GIF、PNG等多种格式的文件,并且能够在Windows、Linux、Unix等多个操作系统上运行。系统首先将各种格式的文件解析为像素矩阵(Matrix),然后将像素矩阵显示在屏幕上,在不同的操作系统中可以调用不同的绘制函数来绘制像素矩阵。系统需具有较好的扩展性以支持新的文件格式和操作系统。

     
Sunny软件集团的开发人士针对上述须求,指出了1个方始设计方案,其基本构造如图10-1所示:

图片 7

       
在图10-1的开始设计方案中,使用了一种多层继承结构,Image是空泛父类,而每个档次的图像类,如BMPImage、JPGImage等作为其直接子类,不相同的图像文件格式具有不一致的解析方法,可以拿走不一样的像素矩阵;由于各个图像又须求在不相同的操作系统中突显,不相同的操作系统在屏幕上展示像素矩阵有所差异,由此必要为不一致的图像类再提供一组在差别操作系统突显的子类,如为BMPImage提供多个子类BMPWindowsImp、BMPLinuxImp和BMPUnixImp,分别用于在Windows、Linux和Unix多个不等的操作系统下显得图像。

       大家前日对该设计方案举办解析,发现存在如下多少个首要难题:

      
(1)由于应用了多层继承结构,导致系统中类的个数急剧扩展,图10-1中,在各类图像的操作系统完毕层提供了拾个具体类,加上各级抽象层的类,系统中类的总个数达到了1多少个,在该设计方案中,具体层的类的个数 = 所辅助的图像文件格式数×所援救的操作系统数。

      
(2)系统扩张麻烦,由于每壹个具体类既涵盖图像文件格式音讯,又包含操作系统消息,由此无论是增加新的图像文件格式依旧增添新的操作系统,都急需扩展大气的具体类,例如在图10-1中追加一种新的图像文件格式TIF,则必要追加二个有血有肉类来促成该格式图像在3种不一样操作系统的显得;尽管扩展1个新的操作系统Mac
OS,为了在该操作系统下可以显示种种别型的图像,需求追加六个具体类。那将导致系统变得要命巨大,扩大运营和爱抚成本。

       怎样缓解那多个难点?大家透过分析可获悉,该序列留存三个单身变化的维度:图像文件格式和操作系统,如图10-2所示:

图片 8

       
在图10-2中,怎么样将各类差异类其他图像文件解析为像素矩阵与图像文件格式本身有关,而哪些在显示器上显得像素矩阵则仅与操作系统相关。正因为图10-1所示结构将这二种义务集中在一个类中,导致系统扩大麻烦,从类的宏图角度解析,具体类BMPWindowsImp、BMPLinuxImp和BMPUnixImp等违反了“单一义务规范”,因为不断壹个挑起它们变化的原因,它们将图像文件解析和像素矩阵突显那二种截然两样的任务融合在一块儿,任意二个职分发生改变都需求修改它们,系统伸张困难。

       
怎么着立异?我们的方案是将图像文件格式(对应图像格式的分析)与操作系统(对应像素矩阵的显示)多个维度分离,使得它们能够独立变化,扩展新的图像文件格式恐怕操作系统时都对另2个维度不造成其余影响。看到那里,大家莫不会问,到底怎么在软件中落到实处将几个维度分离呢?不用着急,本章小编将为大家详细介绍一种用于拍卖多维度转移的设计情势——桥接形式。

处理多维度转变——桥接格局(二)

10.2 桥接形式概述

桥接情势是一种很实用的结构型设计方式,假如软件系统中有些类存在三个单身变化的维度,通过该格局可以将那三个维度分离出来,使双方可以单独伸张,让系统尤其切合“单一职分规范”。与多层继承方案不相同,它将三个单身变化的维度设计为四个单身的一而再等级结构,并且在架空层建立二个架空关联,该关联关系看似一条连接八个独立继承结构的桥,故名桥接方式。

桥接格局用一种高超的措施处理多层继承存在的题材,用抽象关联取代了价值观的多层继承,将类之间的静态继承关系转移为动态的靶子组合关系,使得系统尤其灵敏,并简单增加,同时有效控制了系统中类的个数。桥接定义如下:

桥接方式(Bridge
Pattern):将抽象部分与它的兑现部分分离,使它们都足以独自地转移。它是一种对象结构型格局,又称之为柄体(Handle
and Body)格局或接口(Interface)形式

桥接形式的结构与其名称相同,存在一条连接五个持续等级结构的桥,桥接情势社团如图10-3所示:

图片 9

图 10-3 桥接方式协会

在桥接格局结构图中含有如下多少个角色:

  • Abstraction(抽象类):用于定义抽象类的接口,它一般是抽象类而不是接口,其中定义了1个Implementor(完毕类接口)类型的靶子并得以爱慕该对象,它与Implementor之间全数关联关系,它既可以分包抽象业务方法,也足以涵盖具体事情方法。

  • RefinedAbstraction(伸张抽象类):扩大由Abstraction定义的接口,常常情状下它不再是抽象类而是具体类,它完结了在Abstraction中宣称的悬空业务方法,在RefinedAbstraction中可以调用在Implementor中定义的业务方法。

  • Implementor(达成类接口):定义完结类的接口,那些接口不自然要与Abstraction的接口完全一致,事实上这个接口可以完全两样,一般而言,Implementor接口仅提供基本操作,而Abstraction定义的接口可能会做更多更扑朔迷离的操作。Implementor接口对这个基本操作举办了评释,而实际完毕交给其子类。通过关系关系,在Abstraction中不仅全数和谐的主意,仍是可以调用到Implementor中定义的法门,使用关联关系来取代继承关系。

  • ConcreteImplementor(具体完成类):具体贯彻Implementor接口,在不一样的ConcreteImplementor中提供基本操作的两样完结,在程序运营时,ConcreteImplementor对象将替换其父类对象,提要求抽象类具体的政工操作方法。

在利用桥接格局时,我们第②应该识别出壹个类所全数的多少个单身变化的维度,将它们设计为七个独立的继续等级结构,为多个维度都提供抽象层,并树立抽象耦合。日常意况下,大家将装有三个单身变化维度的类的一些屡见不鲜工作方法和与之提到最缜密的维度设计为“抽象类”层次结构(抽象部分),而将另二个维度设计为“落成类”层次结构(已毕部分)。例如:对于毛笔而言,由于型号是其本来的维度,由此得以设计二个虚无的毛笔类,在此类中宣示并部分贯彻毛笔的事务方法,而将种种型号的毛笔作为其子类;颜色是毛笔的另多少个维度,由于它与毛笔之间存在一种“设置”的关联,由此大家能够提供一个华而不实的水彩接口,而将具体的水彩作为完成该接口的子类。在此,型号可认为是毛笔的架空部分,而颜色是毛笔的贯彻部分,结构示意图如图10-4所示:

图片 10

图 10-4 毛笔结构示意图

在图10-4中,假若急需充实一种新型号的毛笔,只需扩充左边的“抽象部分”,扩充二个新的扩大抽象类;即使需求追加一种新的水彩,只需增加左边的“达成部分”,增添一个新的切切实实贯彻类。扩张分外有利于,无须修改已有代码,且不会导致类的数目增进过快。

在具体编码落成时,由于在桥接方式中留存三个独立变化的维度,为了使两者之间耦合度下跌,首先要求针对两个差其他维度提取抽象类和落实类接口,并确立3个虚幻关联关系。对于“完毕部分”维度,典型的已毕类接口代码如下所示:

interface Implementor {  
    public void operationImpl();  
}

在贯彻Implementor接口的子类中贯彻了在该接口中宣称的法门,用于定义与该维度相对应的局部具体方法。

对此另一“抽象部分”维度而言,其出众的抽象类代码如下所示:

abstract class Abstraction {  

    //定义实现类接口对象 
    protected Implementor impl;  

    public void setImpl(Implementor impl) {  
        this.impl=impl;  
    }  

    //   
    public abstract void operation();   
}

在抽象类Abstraction中定义了二个完成类接口类型的成员对象impl,再通过注入的法门给该目标赋值,一般将该对象的可知性定义为protected,以便在其子类中访问Implementor的措施,其子类一般称为扩大抽象类或细化抽象类(RefinedAbstraction),典型的RefinedAbstraction类代码如下所示:

class RefinedAbstraction extends Abstraction {  
    public void operation() {  
        //业务代码  
        impl.operationImpl();  //调用实现类的方法  
        //业务代码  
    }  
}

对此客户端而言,可以针对两个维度的肤浅层编程,在程序运维时再动态明确三个维度的子类,动态构成对象,将八个独立变化的维度完全解耦,以便可以灵活地扩展任一维度而对另一维度不造成其余影响。

思考

假若系统中留存三个以上的转变维度,是还是不是能够使用桥接方式进行处理?如若得以,系统该怎么统筹?

扩展:适配器格局与桥接格局的联用

图片 11

10.2 桥接情势概述

       
桥接格局是一种很实用的结构型设计格局,若是软件系统中某些类存在多个独立变化的维度,通过该格局可以将这八个维度分离出来,使双边可以独立扩大,让系统越来越契合“单一任务规范”。与多层继承方案差距,它将七个独立变化的维度设计为八个单身的持续等级结构,并且在空洞层建立二个虚非亲非故联,该关联关系看似一条连接四个独立继承结构的桥,故名桥接格局。

       
桥接情势用一种高超的法子处理多层继承存在的难题,用抽象关联取代了观念的多层继承,将类之间的静态继承关系转移为动态的目标组合关系,使得系统特别灵活,并简单增加,同时有效控制了系统中类的个数。桥接定义如下:

桥接模式(Bridge Pattern):将抽象部分与它的实现部分分离,使它们都可以独立地变化。它是一种对象结构型模式,又称为柄体(Handle and Body)模式或接口(Interface)模式。

       
桥接情势的布局与其名目一致,存在一条连接五个接二连三等级结构的桥,桥接情势社团如图10-3所示:

图片 12

        在桥接情势结构图中带有如下多少个脚色:

●Abstraction(抽象类):用于定义抽象类的接口,它一般是抽象类而不是接口,其中定义了二个Implementor(落成类接口)类型的目的并可以维护该目的,它与Implementor之间有着关联关系,它既可以包涵抽象业务方法,也得以分包具体工作方法。

●RefinedAbstraction(增添抽象类):伸张由Abstraction定义的接口,平常状态下它不再是抽象类而是具体类,它完成了在Abstraction中扬言的肤浅业务方法,在RefinedAbstraction中可以调用在Implementor中定义的事情方法。

●Implementor(达成类接口):定义完成类的接口,那个接口不自然要与Abstraction的接口完全一致,事实上那多个接口可以完全分裂,一般而言,Implementor接口仅提供基本操作,而Abstraction定义的接口可能会做更加多更复杂的操作。Implementor接口对这一个基本操作举办了评释,而具体完毕交给其子类。通过涉及关系,在Abstraction中不仅全数自身的不二法门,还能调用到Implementor中定义的情势,使用关联关系来代表继承关系。

●ConcreteImplementor(具体落成类):具体贯彻Implementor接口,在分化的ConcreteImplementor中提供基本操作的例外完成,在程序运维时,ConcreteImplementor对象将替换其父类对象,提要求抽象类具体的业务操作方法。

       
桥接形式是三个不胜实用的方式,在桥接格局中展现了成百上千面向对象设计条件的思考,包罗“单一任务规范”、“开闭原则”、“合成复用原则”、“里氏代换原则”、“重视倒转原则”等。熟练桥接方式牵动大家深入了然这一个布署条件,也助长我们形成不易的规划思想和培训非凡的规划风格。

       
在使用桥接形式时,大家率先应当识别出多少个类所独具的八个独立变化的维度,将它们设计为八个单身的存续等级结构,为五个维度都提供抽象层,并建立抽象耦合。平常状态下,大家将持有多少个单身变化维度的类的一对普通工作方法和与之提到最缜密的维度设计为“抽象类”层次结构(抽象部分),而将另三个维度设计为“完成类”层次结构(已毕部分)。例如:对于毛笔而言,由于型号是其原有的维度,由此得以设计两个虚幻的毛笔类,在此类中扬言并部分完毕毛笔的政工方法,而将各类型号的毛笔作为其子类;颜色是毛笔的另1个维度,由于它与毛笔之间存在一种“设置”的涉及,由此大家可以提供一个浮泛的颜色接口,而将切实的水彩作为落到实处该接口的子类。在此,型号可认为是毛笔的肤浅部分,而颜色是毛笔的兑现部分,结构示意图如图10-4所示:

图片 13

       在图10-4中,假如急需追加一种新型号的毛笔,只需增添左边的“抽象部分”,增添1个新的壮大抽象类;假若须求追加一种新的颜料,只需增加右边的“完毕部分”,扩大三个新的切切实实贯彻类。扩张非常便宜,无须修改已有代码,且不会导致类的多寡增进过快。

 

    在实际编码落成时,由于在桥接形式中留存八个单身变化的维度,为了使两者之间耦合度下落,首先要求针对七个差距的维度提取抽象类和完结类接口,并树立三个虚无关联关系。对于“完结部分”维度,典型的落实类接口代码如下所示:

interface Implementor {  
    public void operationImpl();  
}  

 在已毕Implementor接口的子类中贯彻了在该接口中宣示的点子,用于定义与该维度相对应的某个具体方法。

        对于另一“抽象部分”维度而言,其独立的抽象类代码如下所示:

abstract class Abstraction {  
    protected Implementor impl; //定义实现类接口对象  

    public void setImpl(Implementor impl) {  
        this.impl=impl;  
    }  

    public abstract void operation();  //声明抽象业务方法  

在抽象类Abstraction中定义了三个兑现类接口类型的分子对象impl,再通过注入的主意给该对象赋值,一般将该对象的可知性定义为protected,以便在其子类中走访Implementor的章程,其子类一般称为扩大抽象类或细化抽象类(RefinedAbstraction),典型的RefinedAbstraction类代码如下所示:

class RefinedAbstraction extends Abstraction {  
    public void operation() {  
        //业务代码  
        impl.operationImpl();  //调用实现类的方法  
        //业务代码  
    }  
}  

对此客户端而言,可以针对多少个维度的悬空层编程,在程序运营时再动态明确七个维度的子类,动态构成对象,将三个独立变化的维度完全解耦,以便可以灵活地伸张任一维度而对另一维度不造成其他影响。

 

思考

如果系统中存在两个以上的变化维度,是否可以使用桥接模式进行处理?如果可以,系统该如何设计?

 

处理多维度变迁——桥接格局(三)

10.3 完整消除方案

为了收缩所需转变的子类数目,达成将操作系统和图像文件格式三个维度分离,使它们得以独立改变,萨妮集团开发人士使用桥接情势来重构跨平台图像浏览系统的设计,其主导构造如图10-5所示:

图片 14

图 10-5 跨平台图像浏览器系统结构图

在图10-5中,Image充当抽象类,其子类JPGImage、PNGImage、BMPImage和GIFImage充当伸张抽象类;ImageImp充当完结类接口,其子类WindowsImp、LinuxImp和UnixImp充当具体落到实处类。完整代码如下所示:

//像素矩阵类:辅助类,各种格式的文件最终都被转化为像素矩阵,不同的操作系统提供不同的方式显示像素矩阵  
class Matrix {  
    //此处代码省略  
}  

//抽象图像类:抽象类  
abstract class Image {  
    protected ImageImp imp;  

    public void setImageImp(ImageImp imp) {  
        this.imp = imp;  
    }   

    public abstract void parseFile(String fileName);  
}  

//抽象操作系统实现类:实现类接口  
interface ImageImp {  
    public void doPaint(Matrix m);  //显示像素矩阵m  
}   

//Windows操作系统实现类:具体实现类  
class WindowsImp implements ImageImp {  
    public void doPaint(Matrix m) {  
        //调用Windows系统的绘制函数绘制像素矩阵  
        System.out.print("在Windows操作系统中显示图像:");  
    }  
}  

//Linux操作系统实现类:具体实现类  
class LinuxImp implements ImageImp {  
    public void doPaint(Matrix m) {  
        //调用Linux系统的绘制函数绘制像素矩阵  
        System.out.print("在Linux操作系统中显示图像:");  
    }  
}  

//Unix操作系统实现类:具体实现类  
class UnixImp implements ImageImp {  
    public void doPaint(Matrix m) {  
        //调用Unix系统的绘制函数绘制像素矩阵  
        System.out.print("在Unix操作系统中显示图像:");  
    }  
}  

//JPG格式图像:扩充抽象类  
class JPGImage extends Image {  
    public void parseFile(String fileName) {  
        //模拟解析JPG文件并获得一个像素矩阵对象m;  
        Matrix m = new Matrix();   
        imp.doPaint(m);  
        System.out.println(fileName + ",格式为JPG。");  
    }  
}  

//PNG格式图像:扩充抽象类  
class PNGImage extends Image {  
    public void parseFile(String fileName) {  
        //模拟解析PNG文件并获得一个像素矩阵对象m;  
        Matrix m = new Matrix();   
        imp.doPaint(m);  
        System.out.println(fileName + ",格式为PNG。");  
    }  
}  

//BMP格式图像:扩充抽象类  
class BMPImage extends Image {  
    public void parseFile(String fileName) {  
        //模拟解析BMP文件并获得一个像素矩阵对象m;  
        Matrix m = new Matrix();   
        imp.doPaint(m);  
        System.out.println(fileName + ",格式为BMP。");  
    }  
}  

//GIF格式图像:扩充抽象类  
class GIFImage extends Image {  
    public void parseFile(String fileName) {  
        //模拟解析GIF文件并获得一个像素矩阵对象m;  
        Matrix m = new Matrix();   
        imp.doPaint(m);  
        System.out.println(fileName + ",格式为GIF。");  
    }  
}

为了让系统具备更好的灵活性和可扩大性,大家引入了配备文件,将现实增添抽象类和实际完毕类类名都存储在布局文件中,再经过反射生成对象,将转移的切实落到实处类对象注入到扩展抽象类对象中,其中,配置文件config.xml的代码如下所示:

<?xml version="1.0"?>  
<config>  
    <!--RefinedAbstraction-->  
    <className>JPGImage</className>   
    <!--ConcreteImplementor-->  
    <className>WindowsImp</className>  
</config>

用来读取配置文件config.xml并反射生成对象的XMLUtil类的代码如下所示:

import javax.xml.parsers.*;  
import org.w3c.dom.*;  
import org.xml.sax.SAXException;  
import java.io.*;  
public class XMLUtil {  
//该方法用于从XML配置文件中提取具体类类名,并返回一个实例对象  
    public static Object getBean(String args) {  
        try {  
            //创建文档对象  
            DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();  
            DocumentBuilder builder = dFactory.newDocumentBuilder();  
            Document doc;                             
            doc = builder.parse(new File("config.xml"));   
            NodeList nl=null;  
            Node classNode=null;  
            String cName=null;  
            nl = doc.getElementsByTagName("className");  

            if(args.equals("image")) {  
                //获取第一个包含类名的节点,即扩充抽象类  
                classNode=nl.item(0).getFirstChild();  

            }  
            else if(args.equals("os")) {  
               //获取第二个包含类名的节点,即具体实现类  
                classNode=nl.item(1).getFirstChild();  
            }  

             cName=classNode.getNodeValue();  
             //通过类名生成实例对象并将其返回  
             Class c=Class.forName(cName);  
             Object obj=c.newInstance();  
             return obj;          
           }     
           catch(Exception e) {  
              e.printStackTrace();  
              return null;  
          }  
     }  
}

编制如下客户端测试代码:

class Client {  
    public static void main(String args[]) {  
        Image image;  
        ImageImp imp;  
        image = (Image)XMLUtil.getBean("image");  
        imp = (ImageImp)XMLUtil.getBean("os");  
        image.setImageImp(imp);  
        image.parseFile("小龙女");  
    }  
}

编译并运维程序,输出结果如下:

在Windows操作系统中显示图像:小龙女,格式为JPG。

如果须要更换图像文件格式恐怕更换操作系统,只需修改配置文件即可,在实际应用时,可以通过分析图像文件格式后缀名来规定具体的文件格式,在程序运维时得到操作系统音信来鲜明操作系统类型,无须使用计划文件。当扩大新的图像文件格式或许操作系统时,原有系统无须做任何修改,只需增添多个相应的伸张抽象类或具体贯彻类即可,系统具有较好的可扩大性,完全符合“开闭原则”。

总结

主要优点:
(1)分离抽象接口及其完毕部分。桥接方式采纳“对象间的涉及关系”解耦了抽象和促成之间原有的绑定关系,使得抽象和完结能够本着各自的维度来变化。所谓抽象和贯彻沿着各自维度的成形,约等于说抽象和得以完毕不再在同五个继续层次结构中,而是“子类化”它们,使它们各自都抱有温馨的子类,以便任何组合子类,从而取得多维度结合对象。
(2)在众多状态下,桥接情势可以代表多层继承方案,多层继承方案违反了“单一职分规范”,复用性较差,且类的个数格外多,桥接形式是比多层继承方案更好的化解方法,它极大裁减了子类的个数。
(3)桥接方式提升了系统的可扩充性,在多少个转变维度中随意伸张多少个维度,都不要求修改原有系统,符合“开闭原则”。

重点弱点:
(1)桥接方式的应用会追加系统的明亮与统筹难度,由于涉及关系创建在抽象层,要求开发者一先河就本着抽象层进行设计与编程。
(2)桥接形式须要正确识别出连串中五个单身变化的维度,因而其利用限制有所自然的局限性,如何科学识别八个单身维度也必要自然的经验积累。

10.3  完整消除方案

       
为了减弱所需变更的子类数目,完毕将操作系统和图像文件格式两个维度分离,使它们可以独立改变,Sunny集团开发人员使用桥接方式来重构跨平台图像浏览系统的设计,其主导构造如图10-5所示:

图片 15

         在图10-5中,Image充当抽象类,其子类JPGImage、PNGImage、BMPImage和GIFImage充当增添抽象类;ImageImp充当完成类接口,其子类WindowsImp、LinuxImp和UnixImp充当具体完成类。完整代码如下所示:

//像素矩阵类:辅助类,各种格式的文件最终都被转化为像素矩阵,不同的操作系统提供不同的方式显示像素矩阵  
class Matrix {  
    //此处代码省略  
}  

//抽象图像类:抽象类  
abstract class Image {  
    protected ImageImp imp;  

    public void setImageImp(ImageImp imp) {  
        this.imp = imp;  
    }   

    public abstract void parseFile(String fileName);  
}  

//抽象操作系统实现类:实现类接口  
interface ImageImp {  
    public void doPaint(Matrix m);  //显示像素矩阵m  
}   

//Windows操作系统实现类:具体实现类  
class WindowsImp implements ImageImp {  
    public void doPaint(Matrix m) {  
        //调用Windows系统的绘制函数绘制像素矩阵  
        System.out.print("在Windows操作系统中显示图像:");  
    }  
}  

//Linux操作系统实现类:具体实现类  
class LinuxImp implements ImageImp {  
    public void doPaint(Matrix m) {  
        //调用Linux系统的绘制函数绘制像素矩阵  
        System.out.print("在Linux操作系统中显示图像:");  
    }  
}  

//Unix操作系统实现类:具体实现类  
class UnixImp implements ImageImp {  
    public void doPaint(Matrix m) {  
        //调用Unix系统的绘制函数绘制像素矩阵  
        System.out.print("在Unix操作系统中显示图像:");  
    }  
}  

//JPG格式图像:扩充抽象类  
class JPGImage extends Image {  
    public void parseFile(String fileName) {  
        //模拟解析JPG文件并获得一个像素矩阵对象m;  
        Matrix m = new Matrix();   
        imp.doPaint(m);  
        System.out.println(fileName + ",格式为JPG。");  
    }  
}  

//PNG格式图像:扩充抽象类  
class PNGImage extends Image {  
    public void parseFile(String fileName) {  
        //模拟解析PNG文件并获得一个像素矩阵对象m;  
        Matrix m = new Matrix();   
        imp.doPaint(m);  
        System.out.println(fileName + ",格式为PNG。");  
    }  
}  

//BMP格式图像:扩充抽象类  
class BMPImage extends Image {  
    public void parseFile(String fileName) {  
        //模拟解析BMP文件并获得一个像素矩阵对象m;  
        Matrix m = new Matrix();   
        imp.doPaint(m);  
        System.out.println(fileName + ",格式为BMP。");  
    }  
}  

//GIF格式图像:扩充抽象类  
class GIFImage extends Image {  
    public void parseFile(String fileName) {  
        //模拟解析GIF文件并获得一个像素矩阵对象m;  
        Matrix m = new Matrix();   
        imp.doPaint(m);  
        System.out.println(fileName + ",格式为GIF。");  
    }  
}  

 

 为了让系统具备更好的油滑和可扩张性,大家引入了布署文件,将切实增加抽象类和现实贯彻类类名都存储在陈设文件中,再通过反射生成对象,将转变的现实性完结类对象注入到扩张抽象类对象中,其中,配置文件config.xml的代码如下所示:

[html] view
plain
 copy

 

  1. <?xml version=”1.0″?>  
  2. <config>  
  3.     <!–RefinedAbstraction–>  
  4.     <className>JPGImage</className>   
  5.     <!–ConcreteImplementor–>  
  6.     <className>WindowsImp</className>  
  7. </config>  

       
用于读取配置文件config.xml并反射生成对象的XMLUtil类的代码如下所示:

import javax.xml.parsers.*;  
import org.w3c.dom.*;  
import org.xml.sax.SAXException;  
import java.io.*;  
public class XMLUtil {  
//该方法用于从XML配置文件中提取具体类类名,并返回一个实例对象  
    public static Object getBean(String args) {  
        try {  
            //创建文档对象  
            DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();  
            DocumentBuilder builder = dFactory.newDocumentBuilder();  
            Document doc;                             
            doc = builder.parse(new File("config.xml"));   
            NodeList nl=null;  
            Node classNode=null;  
            String cName=null;  
            nl = doc.getElementsByTagName("className");  

            if(args.equals("image")) {  
                //获取第一个包含类名的节点,即扩充抽象类  
                classNode=nl.item(0).getFirstChild();  

            }  
            else if(args.equals("os")) {  
               //获取第二个包含类名的节点,即具体实现类  
                classNode=nl.item(1).getFirstChild();  
            }  

             cName=classNode.getNodeValue();  
             //通过类名生成实例对象并将其返回  
             Class c=Class.forName(cName);  
             Object obj=c.newInstance();  
             return obj;          
           }     
           catch(Exception e) {  
              e.printStackTrace();  
              return null;  
          }  
     }  
}  

 编写如下客户端测试代码:

class Client {  
    public static void main(String args[]) {  
        Image image;  
        ImageImp imp;  
        image = (Image)XMLUtil.getBean("image");  
        imp = (ImageImp)XMLUtil.getBean("os");  
        image.setImageImp(imp);  
        image.parseFile("小龙女");  
    }  
}  

  编译并运维程序,输出结果如下:

在Windows操作系统中显示图像:小龙女,格式为JPG。

       
借使急需转移图像文件格式恐怕转移操作系统,只需修改配置文件即可,在其实使用时,能够因此分析图像文件格式后缀名来规定具体的文件格式,在程序运维时取得操作系统消息来明确操作系统类型,无须使用安插文件。当增添新的图像文件格式只怕操作系统时,原有系统无须做其余改动,只需追加2个一点青眼的恢弘抽象类或具体完成类即可,系统全体较好的可扩张性,完全符合“开闭原则”。

拍卖多维度生成——桥接方式(四)

10.4 适配器格局与桥接格局的联用

在软件开发中,适配器方式寻常可以与桥接方式联合利用。适配器形式可以缓解多少个已有接口间不包容难题,在那种状态下被适配的类往往是三个黑盒子,有时候大家不想也不能改变这么些被适配的类,也无法控制其增添。适配器格局日常用于现有系统与第一方产品成效的合壹,采用增加适配器的方法将第壹方类集成到系统中。桥接格局则差别,用户可以经过接口继承或类继承的点子来对系统举办伸张。

桥接格局和适配器情势用于设计的不一样等级,桥接情势用于系统的开始设计,对于存在多个单身变化维度的类可以将其分成抽象化和落成化五个角色,使它们得以分别进行转变;而在开端设计完结将来,当发现系统与已有类不只怕协同工作时,可以采纳适配器方式。但有时候在筹划初期也需求考虑适配器格局,尤其是那3个事关到大气第叁方应用接口的情形。

上面通过1个实例来验证适配器方式和桥接情势的一路利用:

在某系统的表格处理模块中,需求将报表突显和数据收集分开,系统可以有多种表格突显格局也能够有各类数额搜集形式,如可以从文本文件中读取数据,也得以从数据库中读取数据,还足以从Excel文件中获取数据。倘使急需从Excel文件中获取数据,则需要调用与Excel相关的API,而那么些API是并存系统所不富有的,该API由厂商提供。使用适配器形式和桥接形式设计该模块。

在规划进度中,由于存在报表突显和多少搜集多个独立变化的维度,因而能够运用桥接形式展开初叶设计;为了使用Excel相关的API来举办数据收集则须要使用适配器方式。系统的全体设计中要求将多个格局联用,如图10-6所示:

图片 16

图 10-6 桥接情势与适配器方式联用示意图

10.5 桥接方式统计

桥接情势是统筹Java虚拟机和落到实处JDBC等驱动程序的宗旨格局之一,应用较为常见。在软件开发中只要一个类或一个连串有七个转移维度时,都足以品尝使用桥接格局对其进展规划。桥接格局为多维度转变的系统提供了一套完整的消除方案,并且下跌了系统的复杂度。

  1. 关键优点

桥接形式的显要优点如下:

(1)分离抽象接口及其完结部分。桥接形式应用“对象间的关系关系”解耦了聊以自慰和已毕之间原有的绑定关系,使得抽象和兑现可以本着各自的维度来扭转。所谓抽象和贯彻沿着各自维度的变迁,约等于说抽象和落到实处不再在同一个持续层次结构中,而是“子类化”它们,使它们各自都有所自个儿的子类,以便任何组合子类,从而得到多维度结成对象。

(2)在重重情景下,桥接格局可以取代多层继承方案,多层继承方案违反了“单一职务规范”,复用性较差,且类的个数相当多,桥接格局是比多层继承方案更好的缓解格局,它极大减弱了子类的个数。

(3)桥接形式进步了系统的可扩大性,在三个转移维度中自由增添七个维度,都不须要修改原有系统,符合“开闭原则”。

  1. 主要缺点

桥接格局的显要弱点如下:

(1)桥接情势的应用会增添系统的明亮与统筹难度,由于涉及关系创建在抽象层,须求开发者一起初就对准抽象层举办设计与编程。

(2)桥接格局须要正确识别出连串中多个单身变化的维度,因而其应用限制有所自然的局限性,怎样正确识别七个单身维度也需求自然的经历积累。

  1. 适用场景

在偏下状况下可以设想使用桥接情势:

(1)如若一个系统要求在抽象化和具体化之间增添更加多的一箭穿心,避免在七个层次之间创设静态的存续关系,通过桥接格局可以使它们在空虚层建立三个事关关系。

(2)“抽象部分”和“已毕部分”可以以一连的办法独立伸张而互不影响,在程序运转时得以动态将1个抽象化子类的靶子和一个落到实处化子类的靶子开展重组,即系统需求对抽象化角色和兑现化角色举行动态耦合。

(3)3个类存在七个(或多少个)独立变化的维度,且那五个(或七个)维度都急需单独开展增添。

(4)对于这一个不期望接纳持续或因为多层继承导致系统类的个数急剧扩张的系统,桥接模式越发适用。

练习

萨妮软件商店欲开发二个数据转换工具,可以将数据库中的数据转换来八种文件格式,例如txt、xml、pdf等格式,同时该工具需求协助多样不一致的数据库。试使用桥接方式对其进行设计。

演习会在我的github上做掉

适用场景

(1)假若3个系列必要在抽象化和具体化之间增添越多的左右逢源,防止在多少个层次之间确立静态的三番三回关系,通过桥接格局可以使它们在空洞层建立二个涉嫌关系。
(2)“抽象部分”和“完毕部分”可以以一连的不二法门独立扩张而互不影响,在程序运维时方可动态将三个抽象化子类的靶子和二个落到实处化子类的对象开展重组,即系统须要对抽象化角色和兑现化角色举行动态耦合。
(3)2个类存在五个(或多个)独立变化的维度,且这多个(或四个)维度都急需独自展开扩充。
(4)对于那几个不期望拔取持续或因为多层继承导致系统类的个数急剧增加的系统,桥接形式越发适用。

10.4 适配器方式与桥接格局的联用

       
在软件开发中,适配器方式平时可以与桥接方式联合使用。适配器格局可以化解多少个已有接口间不兼容难点,在这种意况下被适配的类往往是1个黑盒子,有时候大家不想也无法更改那几个被适配的类,也无法操纵其扩充。适配器格局平日用于现有系统与第一方产品效果的购并,采纳扩张适配器的艺术将第壹方类集成到系统中。桥接格局则分歧,用户可以透过接口继承或类继承的格局来对系统进行伸张。

       
桥接形式和适配器形式用于设计的不一样等级,桥接格局用于系统的初阶设计,对于存在多少个单身变化维度的类可以将其分成抽象化和完毕化多少个剧中人物,使它们可以独家展开转移;而在初叶设计完毕之后,当发现系统与已有类不能协同工作时,可以行使适配器模式。但有时在筹划初期也亟需考虑适配器方式,尤其是这三个关系到大方第壹方使用接口的气象。

        上边通过三个实例来评释适配器方式和桥接方式的一道利用:

       
在某系统的报表处理模块中,要求将报表突显和数据收集分开,系统可以有八种报表突显格局也可以有各个数额收集情势,如可以从文本文件中读取数据,也足以从数据库中读取数据,还足以从Excel文件中获取数据。假如要求从Excel文件中获取数据,则必要调用与Excel相关的API,而以此API是水土保持系统所不负有的,该API由厂商提供。使用适配器情势和桥接形式设计该模块。

       
在筹划进程中,由于存在报表显示和数码收集三个独立变化的维度,因而得以行使桥接方式进行初步设计;为了使用Excel相关的API来拓展多少收集则须要接纳适配器格局。系统的完全设计中需求将八个情势联用,如图10-6所示:

图片 17

 10.5 桥接格局总括

       
桥接方式是规划Java虚拟机和兑现JDBC等驱动程序的中坚方式之一,应用较为常见。在软件开发中一旦3个类或1个系列有七个变化维度时,都可以品尝运用桥接格局对其进展统筹。桥接方式为多维度生成的系统提供了一套完整的缓解方案,并且降低了系统的复杂度。

1.重点优点

        桥接形式的机要优点如下:

       
(1)分离抽象接口及其已毕部分。桥接格局采用“对象间的涉嫌关系”解耦了抽象和促成之间原本的绑定关系,使得抽象和达成可以顺着各自的维度来变化。所谓抽象和兑现沿着各自维度的转移,约等于说抽象和贯彻不再在同3个后续层次结构中,而是“子类化”它们,使它们分别都怀有友好的子类,以便任何组合子类,从而获取多维度组合对象。

       
(2)在诸多气象下,桥接情势可以代替多层继承方案,多层继承方案违反了“单一职务规范”,复用性较差,且类的个数分外多,桥接格局是比多层继承方案更好的缓解方法,它巨大减少了子类的个数。

       
(3)桥接情势提升了系统的可增添性,在五个转移维度中自由增添二个维度,都不需求修改原有系统,符合“开闭原则”。

2.主要缺点

        桥接方式的重点弱点如下:

       
(1)桥接情势的施用会增多系统的领悟与规划难度,由于涉及关系建立在抽象层,须要开发者一开头就本着抽象层开展规划与编程。

       
(2)桥接形式需要正确识别出系统中多个独立变化的维度,因而其拔取范围有着一定的局限性,怎么着正确识别七个独立维度也亟需一定的阅历积累。

3.适用场景

        在偏下情状下可以设想使用桥接形式:

       
(1)若是一个系统需求在抽象化和具体化之间增加越来越多的油滑,防止在两个层次之间创立静态的继承关系,通过桥接格局可以使它们在抽象层建立3个关系关系。

       
(2)“抽象部分”和“完毕部分”能够以屡次三番的章程独立增加而互不影响,在程序运营时得以动态将一个抽象化子类的目的和贰个落实化子类的靶子举办结合,即系统要求对抽象化剧中人物和促成化角色举办动态耦合。

       
(3)1个类存在四个(或多少个)独立变化的维度,且那五个(或多少个)维度都亟待独自开展扩大。

       
(4)对于那几个不希望利用持续或因为多层继承导致系统类的个数急剧伸张的种类,桥接格局越发适用。

 

练习

Sunny软件公司欲开发一个数据转换工具,可以将数据库中的数据转换成多种文件格式,例如txt、xml、pdf等格式,同时该工具需要支持多种不同的数据库。试使用桥接模式对其进行设计。

 

【作者:刘伟  http://blog.csdn.net/lovelion

 

相关文章