VB.NET接口泛型+策略模式+单例模式

前端之家收集整理的这篇文章主要介绍了VB.NET接口泛型+策略模式+单例模式前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

在程序中的数据访问层中,经常会遇到返回实体类的情况,而不同的实体类大多具有相似的代码,情况也大致相同:有的是返回实体类的一条记录,有的是返回实体类的集合。这样如果仅按照最简单的写法的话,程序中会出现许多相似的代码,给人一种不舒服的感觉,如果发现一个程序中有许多重复类似的代码,那么就是程序中的坏味道,我们就应该想办法,对这些代码的实质进行抽象,进行优化,那么接下来要总结的接口泛型就是这么一个例子,另外用到了策略模式+单例模式。有些地方还需要继续优化,不过先把今天实现的功能总结一下。

先来看看UML结构图:

1、解释一下单例模式:BasicDataReaderToEntityStrategy

单例模式有一个自身的组合,需要一个私有化的实例化入口,具备一个全局访问的方法,另外需要明白的是,单例模式的线程安全问题,我的理解是整个程序中再任何时刻只能允许单例的原始对象自身有的动作,如,修改里面的数据等,因此给它自己上一把或者两把锁是必要的了。有关单例模式的5种写法以及各自的特点,可以参考这里:http://www.jb51.cc/article/p-vmfqimdh-tk.html

我再把这里用到的BasicDataReaderToEntityStrategy的相关代码贴出来供大家参考或者讨论。

Imports Model
Imports System.Windows.Forms
Imports System.Collections.Generic
Imports System.Data.sqlClient

'单例模式
Public NotInheritable Class BasicDataReaderToEntityStrategy
    Implements IDataReaderToEntityStrategy(Of BasicData)
    '自身组合
    Shared singleInstance As BasicDataReaderToEntityStrategy = Nothing
    '定义一个静态的系统锁
    Shared ReadOnly padLock As New Object

    '私有化构造函数
    Private Sub New()

    End Sub
    '全局静态属性,唯一实例化入口,双重锁
    Public Shared ReadOnly Property GetInstance() As BasicDataReaderToEntityStrategy
        Get
            If singleInstance Is Nothing Then
                SyncLock padLock
                    If singleInstance Is Nothing Then
                        singleInstance = New BasicDataReaderToEntityStrategy
                    End If
                End SyncLock
            End If
            Return singleInstance
        End Get
    End Property

    '实现策略模式的接口
    Public Function DataReaderToEntity(ByVal dataReader As System.Data.sqlClient.sqlDataReader) As Model.BasicData Implements IDataReaderToEntityStrategy(Of Model.BasicData).DataReaderToEntity
        Dim BasicData As New Model.BasicData
        BasicData.Data_Date = dataReader.Item("Data_Date").ToString
        BasicData.Data_Head = dataReader.Item("Data_Head").ToString
        BasicData.Data_leastTime = dataReader.Item("Data_leastTime").ToString
        BasicData.Data_leastCash = dataReader.Item("Data_leastCash").ToString
        BasicData.Data_prepareTime = dataReader.Item("Data_prepareTime").ToString
        BasicData.Data_Rate = dataReader.Item("Data_Rate").ToString
        BasicData.Data_tempRate = dataReader.Item("Data_tempRate").ToString
        BasicData.Data_Time = dataReader.Item("Data_Time").ToString
        BasicData.Data_unitTime = dataReader.Item("Data_unitTime").ToString
        Return BasicData
    End Function
End Class


2、泛化后的接口:IDataReaderToEntityStrategy

无疑这是这篇博客的重点总结,所谓的接口的泛化就是对接口再进行进一步的抽象,然后遵循一个编译器约定的书写格式,经过实践之后你会感觉也挺简单的,废话不多说,贴代码,供参考:

Imports System
Imports System.Collections.Generic
Imports System.Data
Imports System.Text
Imports System.Data.sqlClient

'策略模式,定义泛型接口:将DataReader的数据返回实体类
Public Interface IDataReaderToEntityStrategy(Of T)
    Function DataReaderToEntity(ByVal dataReader As sqlDataReader) As T
End Interface

解释:这里的 T就是对不同的实体类的进一步抽象,相当于在接口中定义一个占位符,然后在具体的环境中根据需求进行针对性的实例化。

3、sqlServerDALHelp类:

sqlServerDALHelp类不与具体的策略接口的子类BasicDataReaderToEntityStrategy关联,只与他们的父类接口关联,看看代码

''' <summary>
    ''' 执行没有传入参数的存储过程,返回DataReader
    ''' </summary>
    ''' <param name="spName">存储过程名</param>
    ''' <returns>DataReader</returns>
    ''' <remarks></remarks>
    Public Function ExecuteNoProcReader(ByVal spName As String) As sqlDataReader
        Dim dataReader As sqlDataReader = Nothing
        Dim conn As New sqlConnection(connStr)
        Dim cmd As New sqlCommand(spName,conn)
        Try
            conn.Open()
            '当关闭dataReader的时候系统自动关闭数据库连接
            dataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection)
            Return dataReader
        Catch ex As Exception
            MsgBox(ex.Message)
            Return Nothing
        Finally
            '这些语句不能有,因为该函数的返回值dataReader,要供其他函数调用,
            '需要保证dataReader的状态为开启,就像一扇门,如果关着的话,别人是无法进入其中进行操作的。
            'conn.Close()
            'cmd.Dispose()
            'cmd = Nothing
            'dataReader.Close()
        End Try

    End Function
    ''' <summary>
    ''' 利用泛化机制,返回一个泛化接口指定的实体类的一条记录
    ''' </summary>
    ''' <typeparam name="T">泛化的实体类的类型</typeparam>
    ''' <param name="spName">存储过程名</param>
    ''' <param name="strategy">策略接口</param>
    ''' <returns>泛化的实体类的一条记录</returns>
    ''' <remarks></remarks>
    Public Function OperatorProcEntity(Of T)(ByVal spName As String,ByVal strategy As IDataReaderToEntityStrategy(Of T)) As T
        Dim dataReader As sqlDataReader
        dataReader = ExecuteNoProcReader(spName)
        Try
            If dataReader.HasRows = False Then
                MsgBox("没有数据可以读取,您需要先往数据库添加配置信息后,系统才可正常使用!")
                Return Nothing
            Else
                While dataReader.Read()
                    Return strategy.DataReaderToEntity(dataReader)
                End While
            End If
        Catch ex As Exception
            MsgBox(ex.Message)
            Return Nothing
        Finally
            dataReader.Close()
        End Try
    End Function


4、BasicDataDAL类:

上面做了一系列的铺垫,可谓磨刀霍霍向猪羊,此类才是真正的刀子——去执行返回实体类的动作。

这里值得注意的是我不太清楚BasicDataDAL类与BasicDataReaderToEntityStrategy是关联关系?还是依赖关系?下面是代码,望路过的高手多给指点。

Imports System.Windows.Forms
Imports Model.BasicData
Imports Utility
Imports System.Data.sqlClient
Imports System.Collections.Generic
Public Class BasicDataDAL
    Implements IDAL.IBasicDataDAL
    Private sqlHelp As New Utility.sqlServerDALHelp
    Private addParam As New Utility.PublicMethod
    ''' <summary>
    ''' 获取基本配置表对象
    ''' </summary>
    ''' <returns>基本配置表实体类</returns>
    ''' <remarks></remarks>  
    Public Function GetData() As Model.BasicData Implements IDAL.IBasicDataDAL.GetData
        Dim spName As String
        spName = "proc_GetBasicData"
        Try
            Return sqlHelp.OperatorProcEntity(spName,BasicDataReaderToEntityStrategy.GetInstance())
        Catch ex As Exception
            MsgBox(ex.Message)
            Return Nothing
        End Try
    End Function

这样就在DAL层完成了一个返回基本表实体类的一条记录的操作,剩下的工作就交代给其他的各层去执行就行,没有其他的变化。

有关泛化的进一步深入,可参考:http://www.yesky.com/SoftChannel/72342380468240384/20041116/1876323.shtml

猜你在找的VB相关文章