当前位置: 首页 > news >正文

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

相关文章:

  • pku-2909 (欧拉筛)
  • 03.万恶之源-基本数据类型(int, bool, str)
  • VS2005新体验
  • .NetCore实践篇:分布式监控Zipkin持久化之殇
  • 【转】javascript 进制转换(2进制、8进制、10进制、16进制之间的转换)
  • [转]SQL Server利用数据库日志恢复数据到时间点的操作
  • fastJson
  • 做最好的自己
  • [导入]上传大文件时,找不到服务器的错误问题!
  • python第一课
  • 基于WinXP sp2配置biztalk2004遇到的问题及解决
  • 多线程笔记——1
  • 八大排序算法
  • Andorid自定义attr的各种坑
  • 发送邮件代码--ASP.NET中常用代码之一
  • 【跃迁之路】【444天】程序员高效学习方法论探索系列(实验阶段201-2018.04.25)...
  • ES6, React, Redux, Webpack写的一个爬 GitHub 的网页
  • Go 语言编译器的 //go: 详解
  • Gradle 5.0 正式版发布
  • Java 内存分配及垃圾回收机制初探
  • JS函数式编程 数组部分风格 ES6版
  • markdown编辑器简评
  • Python进阶细节
  • react 代码优化(一) ——事件处理
  • storm drpc实例
  • underscore源码剖析之整体架构
  • 闭包--闭包之tab栏切换(四)
  • 从输入URL到页面加载发生了什么
  • 浮动相关
  • 工作手记之html2canvas使用概述
  • 世界编程语言排行榜2008年06月(ActionScript 挺进20强)
  • 微信小程序填坑清单
  • 问:在指定的JSON数据中(最外层是数组)根据指定条件拿到匹配到的结果
  • 以太坊客户端Geth命令参数详解
  • 异常机制详解
  • ​卜东波研究员:高观点下的少儿计算思维
  • ​软考-高级-系统架构设计师教程(清华第2版)【第12章 信息系统架构设计理论与实践(P420~465)-思维导图】​
  • ​一、什么是射频识别?二、射频识别系统组成及工作原理三、射频识别系统分类四、RFID与物联网​
  • ​直流电和交流电有什么区别为什么这个时候又要变成直流电呢?交流转换到直流(整流器)直流变交流(逆变器)​
  • # Python csv、xlsx、json、二进制(MP3) 文件读写基本使用
  • ###51单片机学习(1)-----单片机烧录软件的使用,以及如何建立一个工程项目
  • $.ajax()参数及用法
  • (1)(1.8) MSP(MultiWii 串行协议)(4.1 版)
  • (4) PIVOT 和 UPIVOT 的使用
  • (4)logging(日志模块)
  • (二)换源+apt-get基础配置+搜狗拼音
  • (分布式缓存)Redis分片集群
  • (六) ES6 新特性 —— 迭代器(iterator)
  • (十)DDRC架构组成、效率Efficiency及功能实现
  • (转载)CentOS查看系统信息|CentOS查看命令
  • .MyFile@waifu.club.wis.mkp勒索病毒数据怎么处理|数据解密恢复
  • .NET LINQ 通常分 Syntax Query 和Syntax Method
  • .net mvc actionresult 返回字符串_.NET架构师知识普及
  • .net程序集学习心得
  • .net的socket示例