Dot Net设计模式—桥接模式

1.概述
1.1意图

        “将抽象部分与它的实现部分分离,使它们都可以独立地变化”,这是GOF在《设计模式》一书中的解释。这里的抽象和实现并不一定是同一层次的概念,例如数据库操作可以归结为“增加、删除和修改”。很多业务过程都是通过对数据库的操作实现的,例如“库存管理”中的“入库”,这个业务动作的软件实现可以描述为“在库存表中增加一条记录”,而“入库”和“插入记录”处于不同的业务层次。

1.2使用场合
        在如下情况下可以使用桥接模式。
(1)不希望在业务和业务的软件实现之间存在因定的绑定关系。例如,不希望“入库”业务过程和具体的数据库访问技术或数据库管理系统有过于密切的关系。最好是数据库访问技术的升级,或数据库管理系统的改变对业务模块没有影响,甚至在运行期间可以通过动态绑定来选择不同数据库技术或数据库管理系统。
(2)希望类的抽象和实现部分可以扩充,进而实现不同的抽象接口和实现部分的组合。
(3)修改实现部分对用户不产生影响,即代码无须重新编译。
(4)复用实现部分。由于实现部分所处的层次较低,因此可以被多种业务模块复用。例如,数据库访问模块可以用在多种业务单元中。

1.3结构
桥接模式的结构如图所示。
                         %E6%A1%A5%E6%8E%A5%E6%A8%A1%E5%BC%8F%E7%9A%84%E7%BB%93%E6%9E%84.jpg

(1)Abstraction:定义抽象类的接口并维护指向Implementor类的对象指针。
(2)RefinedAbstraction:扩充Abstraction定义的接口。
(3)Implementor:定义实现类的接口,该接口不一定要与Abstraction的接口完全一致。
事实上这两个接口可以完全不同。一般而言,Implementor接口仅提供基本操作,而Abstraction则定义了基于操作的较高层次的操作。
(4) ConcreteImplementor:实现Implementor接口并定义它的具体实现。
        为了更深入了解这个模式,我们来看一个具体的例子。在应用系统中经常有很多业务单元在很多业务模块中类似,隐含在背后的业务域模型相同。例如,“设备管理”中的“零部件管理”,“物资管理”中的“库房管理”,“实验室管理”中的“试剂管理”等都是“库存管理”。但由于业务场景的不同,导致业务中的细节不同,因此不能简单地复用。另外,“库存管理”软件的实现主要通过操作关系数据库来完成,我们希望保持软件系统与数据库访问技术以及数据库管理系统的独立性。

        为了实现以上要求,我们可以以桥接模式。即将抽象的“库存管理”和“数据库”操作作为具体的“库存管理”应用和具体的“数据库访问技术”的桥梁, 如下图所示。
                     %E5%BA%94%E7%94%A8%E6%A1%A5%E6%8E%A5%E6%A8%A1%E5%BC%8F.jpg
           从图中可以看出,我们将库存管理的抽象业务域模型封装在“抽象的库存管理”中。具体的库存管理业务如“生产车间库存管理”可以通过继承库存管理获得一般性的业务过程,然后根据具体的业务特点进行相应的扩展。
我们将数据库操作封装在dbOperation类中,具体执行访问数据库的各个指令,针对具体数据库的操作由该类的子类实现。

  1.4效果
采用桥接模式可以获得以下好处。
(1)将接口与实现分离:一个接口可以有若干实现,一个实现也可以为若干对象服务,表示逻辑的对象可以动态地与实现功能的对象组合。
(2)提高可扩充性:逻辑和实现都可以通过类层次的扩展进行扩充。
需要注意的是,逻辑和实现被封装在不同的对象中,逻辑对实现的引用是动态进行的。在实际中,需要分别用不同的工厂创建逻辑和实现,然后组装。

2.多种数据源与多种数据显示方式的组合
        桥接模式同样可用在多种数据采集方式的场合,在有生产过程实时数据采集时,经常遇到多种数据采集的接口。为适应这种情况,可以采用桥接模式,其结构如图所示。
                   %E7%94%A8%E6%A1%A5%E6%8E%A5%E5%AE%9E%E7%8E%B0%E5%A4%9A%E7%A7%8D%E6%95%B0%E6%8D%AE%E9%87%87%E9%9B%86%E6%8E%A5%E5%8F%A3%E7%9A%84%E7%BB%93%E6%9E%84.jpg

        针对不同的数据源有不同的数据采集方式,有的采集系统需要直接从文件中读取数据,有的需要从远程Web服务器读取数据,有的需要从实时数据库读取数据,有的需要从关系数据库读取数据等。数据采集系统是低层平台,在上层应用中需要各种方式的显示形式,例如流程图、表格、曲线图和趋势图等。每种显示方式模块都可能从不同的数据源接收数据,即不同类型的数据源和数据显示方式应该可以任意组合。

        以一个来源于实际项目的例子说明。我们需要在Web页面上显示流程图,并且需要生成XML格式的流程图文件。其中采用简单工厂获得数据来源,数据来源标志保存在Web.config文件中。

        下图所示为应用的局部结构,其中采用了桥接模式。
                    %E5%BA%94%E7%94%A8%E7%9A%84%E5%B1%80%E9%83%A8%E7%BB%93%E6%9E%84.jpg

下面是部分代码,限于篇幅,仅列出结构部分。
定义clsAbstractReadData类,其中定义了需要获得数据的结构:
 1 None.gif Imports  System.IO
 2 None.gif Imports  System.Net
 3 None.gif  Imports  System.Text
 4 ExpandedBlockStart.gifContractedBlock.gif Public   MustInherit   Class clsAbstractReadData Class clsAbstractReadData
 5ExpandedSubBlockStart.gifContractedSubBlock.gif Public MustOverride Function ReadData()Function ReadData(ByVal strDate As strDate As DataSet
 6InBlock.gif Protected mySourceDs As DataSet
 7ExpandedSubBlockStart.gifContractedSubBlock.gif Public Sub New()Sub New( )
 8InBlock.gif     MySourceDS = New DataSet
 9InBlock.gif     Dim dt As DataTable
10InBlock.gif     ‘这里定义数据结构,省略 
11ExpandedSubBlockEnd.gif End Sub

12ExpandedBlockEnd.gifEnd Class

13 None.gif

具体的读取类实现ReadData方法。下面是从文本文件中读取数据,其中给出了读取用逗号分隔数据的方法:
 1 ExpandedBlockStart.gif ContractedBlock.gif Public   Class clsReadDataFromFile Class clsReadDataFromFile
 2InBlock.gif    Inherits ClsAbstractReadData
 3InBlock.gif    Private datafilepath As String
 4InBlock.gif
 5ExpandedSubBlockStart.gifContractedSubBlock.gif    Public Sub New()Sub New(ByVal strpath As String)
 6InBlock.gif        MyBase.New( )
 7InBlock.gif        Datafilepath = strpath
 8ExpandedSubBlockEnd.gif    End Sub

 9ExpandedSubBlockStart.gifContractedSubBlock.gif    Public Overrides Function ReadData()Function ReadData(ByVal strDate As StringAs
10InBlock.gifSystem.Date.DataSet
11InBlock.gif‘调用ReadDataFromFile从具体的文件中读取数据,省略
12InBlock.gifReturn mysourceds
13ExpandedSubBlockEnd.gif    End Function

14ExpandedSubBlockStart.gifContractedSubBlock.gif    Private Sub ReadDataFromFile()Sub ReadDataFromFile(ByVal fn As String,,ByVal dt As DataTable,ByVal
15InBlock.gif cn As Integer )
16InBlock.gif        ‘fn 数据文件名
17InBlock.gif        ‘dt DtatTable
18InBlock.gif        ‘cn 字段数
19InBlock.gif        Dim fileNumber As Integer
20InBlock.gif        FileNumber = FreeFile( )
21InBlock.gif        FileOpen(fileNumber, fn, OpenMode.Input)
22InBlock.gif        Dim NextLine As String
23InBlock.gif        I = 1
24InBlock.gif        Do Until EOF(fileNumber)
25InBlock.gif            NextLine = LineInput(fileNumber)
26InBlock.gif            If I > 1 And Trim(NextLine) <> “ ” Then
27InBlock.gif              Dim j As Integer
28InBlock.gif              Dim r As DataRow = dt.NewRow
29InBlock.gif              Dim s As String = “ ,”
30InBlock.gif              Dim sp As Char( ) = s.ToCharArray
31InBlock.gif              Dim rs As String( ) = NextLine.Split(sp)
32InBlock.gif              For j = 0 To cn – 1
33InBlock.gif                 Dim v As String
34InBlock.gif                 Try
35InBlock.gif                    V = rs ( j )
36InBlock.gif                    r.Item( j ) = Trim( v )
37InBlock.gif                 Catch ex As Exception
38InBlock.gif                    r.Item( j ) = “ ”
39InBlock.gif                 End Try
40InBlock.gif              Next
41InBlock.gif              Dt.Rows.Add(r)
42InBlock.gif         End If 
43InBlock.gif         I = I + 1
44InBlock.gif     Loop
45InBlock.gif     FileClose(fileNumber)
46ExpandedSubBlockEnd.gifEnd Sub

47ExpandedSubBlockStart.gifContractedSubBlock.gifPrivate Function IsFileExist()Function IsFileExist (ByVal fn As StringAs Boolean
48InBlock.gif   If FileSystem.Dir (fn) = “ ” Then Return False
49InBlock.gif   Return True
50ExpandedSubBlockEnd.gifEnd Function

51ExpandedBlockEnd.gifEnd Class

52 None.gif

下面是产生读取对象的简单工厂:
 1 ExpandedBlockStart.gif ContractedBlock.gif Public   Class clsReaDataFactory Class clsReaDataFactory
 2ExpandedSubBlockStart.gifContractedSubBlock.gif    Pbulic Shared Function getDataReader()Function getDataReader ( ) As clsAbstractReadData
 3InBlock.gif        Dim datafilepath As String = 
 4InBlock.gifConfigurationSettings.AppSettings (“DataFilePath”)
 5InBlock.gif    Dim strDataType As String = ConfigurationSettings.AppSettings (“DataType”)
 6InBlock.gifDim strHttp As String = ConfigurationSettings.AppSettings (“DataURL”)
 7InBlock.gifSelect Case strDataType
 8InBlock.gif    Case “http”
 9InBlock.gif        Dim mrd As clsReadDataFromRemoteFile
10InBlock.gif        Mrd = New clsReadDataFromRemoteFile (strHttp)
11InBlock.gif        Return mrd 
12InBlock.gif    Case Else
13InBlock.gif        Dim mrd As clsReadDataFromFile
14InBlock.gif        Mrd = New clsReadDataFromFile(datafilepath)
15InBlock.gif        Return mrd 
16InBlock.gif    End Select
17ExpandedSubBlockEnd.gif  End Function

18ExpandedBlockEnd.gifend class

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值