加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MsSql教程 > 正文

工厂模式的应用实例

发布时间:2020-12-12 14:36:18 所属栏目:MsSql教程 来源:网络整理
导读:就拿机房收费系统来说吧。 NUMBER ONE 单纯的用抽象工厂来实现。这样的好处,是从整个系统的全局出发,而不单单从原始的 D 看待,古人云:父母之爱子则为之计深远。这使得系统更容易扩展了。因为这里面除了 SQLHelper 都使用了实体包,实体包的线就省略了。


就拿机房收费系统来说吧。

NUMBER ONE

单纯的用抽象工厂来实现。这样的好处,是从整个系统的全局出发,而不单单从原始的D看待,古人云:父母之爱子则为之计深远。这使得系统更容易扩展了。因为这里面除了SQLHelper都使用了实体包,实体包的线就省略了。

NUMBER TWO

?

"简单工厂"去改造的抽象工厂。

这里说的简单工厂只是因为它没有工厂接口。而事实上因为我们的机房收费系统是用对一簇产品进行创建使用,按理说一簇产品应该是抽象工厂的。这样的好处是,在D层实现了解耦,和抽象工厂比起来,我们要扩展的话,BLL层和IFactory改动较大。

NUMBER THREE

"简单工厂"和抽象工厂结合改造后,再加上配置文件。

?与NUMBER ONE不同的是去掉一条线。这样子的好处是去除了DALFactory与实际功能类DAL的耦合。

?

?

?

?

当然如果找个平衡点的话,我们的最佳选择是用NUMBER THREE

代码如下。(一下代码均以登录为例。UI省略)

NUMBER ONE

BLL层。

'------------------------------------------------------------------------------
'?<copyright?file="DALUser.vb"?company="FANG">
'?Copyright?(c)?2012?FANG.?All?rights?reserved.
'?<copyright>
'?<author>The?Sky?Always?Sunshine<author>
'?<author>我的博客地址http://blog.csdn.net/xhf55555</author>
'?<date>2012年2月3日<date>
'?<description>
'BLL层之登录。
'?<description>
'------------------------------------------------------------------------------
Public?Class?BLL_Login
 
????Public?Function?Login(ByVal?User?As?Entity.EN_User)?As?Boolean
????????Dim?myUser?As?New?Entity.EN_User
????????'确定实例化哪个数据库给Factory,来实现换DB。
????????Dim?factory?As?Ifactory.Ifactory?=?New?DALFactory.SqlserverFactory
????????Dim?IUser?As?IDAL.IUser
????????'与具体的数据库访问解除了依赖。
????????IUser?=?factory.CheckUser()
????????myUser?=?IUser.GetUser(User)
????????If?myUser.UserPwd?=?User.UserPwd?Then
????????????Return?True
????????Else
????????????Return?False
????????End?If
 
????End?Function
 
End?Class


IDAL层。

?

'''?<summary>
'''?用户表功能接口。
'''?</summary>
'''?<remarks></remarks>
Public?Interface?IUser
????Function?GetUser(ByVal?User?As?Entity.EN_User)?As?Entity.EN_User
End?Interface

DAL层。(以SqlserverUser为例。)

?

Public?Class?SqlserverUser?:?Implements?IDAL.IUser
 
????Public?Function?GetUser(ByVal?User?As?Entity.EN_User)?As?Entity.EN_User?Implements?IDAL.IUser.GetUser
????????Dim?ConnStr?As?String?=?"Data?Source=192.168.24.169;Initial?Catalog=PC_ChargeSys;User?ID=sa;Pwd=123456"
????????Dim?conn?As?SqlConnection?=?New?SqlConnection(ConnStr)
 
????????'?Dim?connection?As?New?SQLHelp.ConnectionHelp
????????Dim?sql?As?String?=?"select?*?from?tb_User?where?UserID='"?&?User.UserID?&?"'"
????????Dim?cmd?As?SqlCommand?=?New?SqlCommand(sql,?conn)
????????Dim?read?As?SqlDataReader
????????Dim?myUser?As?New?Entity.EN_User
????????Try
????????????conn.Open()
????????????read?=?cmd.ExecuteReader
????????????read.Read()
????????????myUser.UserID?=?read.Item("")
????????????myUser.UserPwd?=?read.Item("UserPwd")
????????????Return?myUser
????????Catch?ex?As?Exception
????????????myUser.UserID?=?0
????????????myUser.UserPwd?=?""
????????????Return?myUser
????????End?Try
 
????End?Function
End?Class


?

IFactory层。

'''?<summary>
'''?定义操作工厂接口。
'''?</summary>
'''?<remarks></remarks>
Public?Interface?Ifactory
????Function?CheckUser()?As?IDAL.IUser
End?Interface


?SqlserverFactory具体操作工程类。

'------------------------------------------------------------------------------
'?<copyright?file="DALUser.vb"?company="FANG">
'?Copyright?(c)?2012?FANG.?All?rights?reserved.
'?<copyright>
'?<author>The?Sky?Always?Sunshine<author>
'?<author>我的博客地址http://blog.csdn.net/xhf55555</author>
'?<date>2012年2月3日<date>
'?<description>
'具体的操作类工厂实现抽象的功能类接口。
'?<description>
'------------------------------------------------------------------------------
Public?Class?SqlserverFactory?:?Implements?Ifactory.Ifactory
????Public?Function?CheckUser()?As?IDAL.IUser?Implements?Ifactory.Ifactory.CheckUser
????????Return?New?DAL.SqlserverUser
????End?Function
End?Class


AccessFactory(与Sqlserver相似,不再赘余。)

?

User实体类。

'User实体类。
Public?Class?EN_User
????Dim?intUserID?As?Integer??'定义用户编号变量。
????Dim?strUserName?As?String??'定义用户姓名变量。
????Dim?strUserPwd?As?String?'定义用户密码变量名。
????Dim?strUserActor?As?String?'定义用户角色变量。
????Dim?vntUserRegDate?As?Date?'定义用户注册日期。
????Dim?strUserFlag?As?String?'定义用户是否合法的标记的变量。
????Dim?strUserType?As?String?'定义用户类型变量。
????'''?<summary>
????'''?用户编号属性方法。
????'''?</summary>
????'''?<value></value>
????'''?<returns></returns>
????'''?<remarks></remarks>
????Public?Property?UserID()?As?Integer
????????Get
????????????Return?intUserID
????????End?Get
 
????????Set(ByVal?value?As?Integer)
????????????intUserID?=?value
????????End?Set
????End?Property
????'''?<summary>
????'''?定义用户名属性方法。
????'''?</summary>
????'''?<value></value>
????'''?<returns></returns>
????'''?<remarks></remarks>
????Public?Property?UserName()?As?String
????????Get
????????????Return?strUserName
????????End?Get
????????Set(ByVal?value?As?String)
????????????strUserName?=?value
????????End?Set
????End?Property
????'''?<summary>
????'''?定义用户密码属性方法?。
????'''?</summary>
????'''?<value></value>
????'''?<returns></returns>
????'''?<remarks></remarks>
????Public?Property?UserPwd()?As?String
????????Get
????????????Return?strUserPwd
????????End?Get
????????Set(ByVal?value?As?String)
????????????strUserPwd?=?value
????????End?Set
????End?Property
????'''?<summary>
????'''?定义用户角色属性方法。
????'''?</summary>
????'''?<value></value>
????'''?<returns></returns>
????'''?<remarks></remarks>
????Public?Property?UserActor()?As?String
????????Get
????????????Return?strUserActor
????????End?Get
????????Set(ByVal?value?As?String)
????????????strUserActor?=?value
????????End?Set
????End?Property
????'''?<summary>
????'''?定义注册日期变量。
????'''?</summary>
????'''?<value></value>
????'''?<returns></returns>
????'''?<remarks></remarks>
????Public?Property?UserRegDate?As?Date
????????Get
????????????Return?vntUserRegDate
????????End?Get
????????Set(ByVal?value?As?Date)
????????????vntUserRegDate?=?value
????????End?Set
????End?Property
????'''?<summary>
????'''?定义用户是否合法的标记。(看是否是已经注销)
????'''?</summary>
????'''?<value></value>
????'''?<returns></returns>
????'''?<remarks></remarks>
????Public?Property?UserFlag?As?String
????????Get
????????????Return?strUserFlag
????????End?Get
????????Set(ByVal?value?As?String)
????????????strUserFlag?=?value
????????End?Set
????End?Property
????'''?<summary>
????'''?定义用户类型变量(是固定用户还是临时用户)
????'''?</summary>
????'''?<value></value>
????'''?<returns></returns>
????'''?<remarks></remarks>
????Public?Property?UserTyep()?As?String
????????Get
????????????Return?strUserType
????????End?Get
????????Set(ByVal?value?As?String)
????????????strUserType?=?value
????????End?Set
????End?Property
 
End?Class

我们再看NUMBER TWO 用简单工厂改造的抽象工厂。

我们是去掉了IFactory工厂接口和他手下的具体工厂操作类,而用一个DALFactory代替解决。这样把对功能类的判断放到了DALFactory里通过SelectCase来进行判断而不是通过实例化来判断了。

UI、IUser、AccessUser、SqlserverUser是不变的。所以在以上基础上改变 ,代码如下。

BLL层代码。

?

''' <summary>
''' 用户登录业务逻辑。
''' </summary>
''' <remarks></remarks>
Public Class BLL_Login
    Public Function Login(ByVal User As Entity.EN_User) As Boolean
        Dim myUser As New Entity.EN_User
        '通过具体的操作工厂实现要判断使用哪个数据库。
        Dim Dalfactory As New DALFactory.DFactory
        Dim IUser As IDAL.IUser
        '与具体的数据库访问解除了依赖。
        IUser = Dalfactory.CreateUserInfo()
        myUser = IUser.GetUser(User)
        If myUser.UserPwd = User.UserPwd Then
            Return True
        Else
            Return False
        End If

    End Function
End Class


DALFactory层。

Imports IDAL
''' <summary>
''' 操作工厂类。
''' </summary>
''' <remarks></remarks>
Public Class DFactory
    'Dim DataBase As String = "Access"
    Dim DataBase As String = "Sql"
    Function CreateUserInfo() As IDAL.IUser
        Dim db As IUser
        Select Case DataBase
            Case "Sql"
                db = New DAL.SqlserverUser
                'Case "Access"
                '   db = New DAL.AccessUser

        End Select
        Return db
    End Function

NUMBER THREE我们是改变了操作工厂case而用反射的方法,和case说拜拜。我们用case判断太过于发死,把字符串写死在了DALFactory中,我们对功能类的使用,不是功能类本身去决定自己。我们要自己决定自己的人生大事,所以用反射就可以了。这样解除了分支判断的耦合。

DALFactory代码。

Imports IDAL
Imports System.Reflection
''' <summary>
''' 操作工厂类。
''' </summary>
''' <remarks></remarks>
Public Class DFactory
    'Dim DataBase As String = "Access"
    'Dim DataBase As String = "Sql"
    Dim strDB As String = System.Configuration.ConfigurationSettings.AppSettings("DBString")
    Function CreateUserInfo() As IDAL.IUser
        
        Return CType(Assembly.Load("DAL").CreateInstance("DAL.SqlserverUser" & strDB),IDAL.IUser)

    End Function

End Class


具体的功能类SqlserverUser,只是改了一句话。

?

Public Class SqlserverUser : Implements IDAL.IUser
    Public Function GetUser(ByVal User As Entity.EN_User) As Entity.EN_User Implements IDAL.IUser.GetUser
        'Dim ConnStr As String = "Data Source=192.168.24.169;Initial Catalog=PC_ChargeSys;User ID=sa;Pwd=123456"
        Dim ConnStr As String = System.Configuration.ConfigurationSettings.AppSettings("ConnStr")

        Dim conn As SqlConnection = New SqlConnection(ConnStr)

        'Dim connection As New SQLHelp.ConnectionHelp
        'connection.Connect()
        Dim sql As String = "select * from tb_User where UserID='" & User.UserID & "'"
        Dim cmd As SqlCommand = New SqlCommand(sql,conn)
        Dim read As SqlDataReader
        Dim myUser As New Entity.EN_User
        Try
            conn.Open()
            read = cmd.ExecuteReader
            read.Read()
            myUser.UserID = read.Item("")
            myUser.UserPwd = read.Item("UserPwd")
            Return myUser
        Catch ex As Exception
            myUser.UserID = 0
            myUser.UserPwd = ""
            Return myUser
        End Try

    End Function

End Class


?工厂模式的基本原理见:http://www.voidcn.com/article/p-butonjbw-bep.html

?综上,我们把简单工厂、工厂方法、和抽象工厂三个模式在实际应用中进行了比较。我们的最佳组合是简单工厂改造的抽象工厂加上配置文件,耦合度和系统的开闭(对扩展开放、对修改封闭)、系统的可维护和灵活性尽在我们的三个包图中。笔者(me)认为,我们的设计模式就像数学公式,灵活运用就好。我们在开发一个系统的时候思考问题不要从上向下的思考方式,我们要从下向上,不是因为解耦而解耦,而是我们从系统长远的角度出发,使得我们在系统在不断的重构中发现问题,才去不断的思考,进一步的抽象,使得系统更加完美。没有完美的系统,只有完美的过程。

?

?

?

?

问题多多,欢迎您前来指教!

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读