工厂模式的应用实例
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
? '''?<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
'------------------------------------------------------------------------------ '?<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
? 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
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
? 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
?综上,我们把简单工厂、工厂方法、和抽象工厂三个模式在实际应用中进行了比较。我们的最佳组合是简单工厂改造的抽象工厂加上配置文件,耦合度和系统的开闭(对扩展开放、对修改封闭)、系统的可维护和灵活性尽在我们的三个包图中。笔者(me)认为,我们的设计模式就像数学公式,灵活运用就好。我们在开发一个系统的时候思考问题不要从上向下的思考方式,我们要从下向上,不是因为解耦而解耦,而是我们从系统长远的角度出发,使得我们在系统在不断的重构中发现问题,才去不断的思考,进一步的抽象,使得系统更加完美。没有完美的系统,只有完美的过程。 ? ? ? ? 问题多多,欢迎您前来指教! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |