WinForm下多层架构的实现

    最近在CSDN上看到有朋友求Winform的三层架构的示例,网上也确实没有多少是Winform的。于是本人牺牲一点时间,做了这个小Demo,希抛砖引玉,望各路老手不吝指教。
    至于什么是“三层结构”、三层结构有什么好处、为什么要用三层结构,我想这些讨论,网上大把,Google 或者 Baidu一下就有一大串。我也就不多说,直接用一个例子来讲述如何实现一个多层架构的WinForm程序。
    在该例子,我选用的是VS.net 2005 + Access 实现,考虑至数据库的可移槙性,数据访问层使用工厂模式,利用.net 的反射在运行时根据配置文件来动态决定采用何用数据库。
    好了,进入正题:
    首先,设定数据库如下 :

字段名称

数据类型

默认值

备注说明

BS_NO Text

N''

工号
BS_NAME Text

N‘’

姓名






    对于,多层架构,我一般都按照预先新建一个空的方案。然后分别新加EntityReflect(实体层)、DALFactory(数据访问层,工厂类),Business(中间业务层)、WinForm(表示界面层),并设定WinForm为启始专案,该专案为WinForm模板,其它全部可作为Class Library模板,设定各专案的相依:Business依赖DALFactory、WinForm依赖Business,完了之后,选取整个方案,编译。在Business层引用DALFactory、WinForm层中引用Business.至上上面的数据访问层并没有针对特定的数据库的数据访问类,所以,再加一个DataAccess Class Library层,该层就是专门针对Access数据访问的。同样设定该层依赖DALFactory,并参考引用DALFactory.再次编译一次,我们就进入代码编制阶段了。
    其实,我们上面的操作,已基本上具备了我上面所说了这个Demo的全部内容了,只是还没有代码而已啦。好,下面我们就添加代码:
    打开EntityReflect专案,将默认的Class1.cs 改为EREmployee.cs,这就是我们的实体规范层,关于这个,我们可以在网上下载一些工具自动生成。不过,在我这个方案,我却一直没有在任何地方引用他。原因其实是我自己也不是很能弄清为什么一定要这个规范层。不过,我还是写了如下的代码:
using  System;
using  System.Collections.Generic;
using  System.Text;

namespace  EntityReflect
{
    
public  class  EREmployee
    {
        
public  EREmployee()
        {
        }
        
private  String strbs_no;
        
private  String strbs_name;
        
public  String strBS_NO
        {
            
get  {  return  strbs_no; }
            
set  { strbs_no  =  value; }
        }
        
public  String strBS_NAME
        {
            
get  {  return  strbs_name; }
            
set  { strbs_name  =  value; }
        }
    }
}

    展开DALFactory层.新加一个IDataAccessObject.cs,目的是为了规范各种数据库访问数据库时使用相同的方法,该接口的代码如下:
using  System;
using  System.Data;

namespace  DALFactory
{
    
public  interface  IDataAccessObject
    {
        
void  Query(DataSet ds,  string  strTableName);
        
void  Save( string  strBS_NO,  string  strBS_NAME);
    }
}
    另外,由于我使用了C#的RTTI,所以,还加了一个类GetDatabaseType.cs,代码如下:
using  System;
using  System.Configuration;
using  System.Reflection;

namespace  DALFactory
{
    
public    class  GetDatabaseType
    {
        
public  IDataAccessObject GetDatabase()
        {
            
string  strAssemblyName  =  ConfigurationManager.AppSettings[ " AssemblyName " ];
            
string  strConstractor  =  ConfigurationManager.AppSettings[ " Constractor " ];
            
return  (IDataAccessObject)Assembly.Load(strAssemblyName).CreateInstance(strConstractor,  false );
        }
    }
}
   
    有了数据访问层的工厂,展开DataAccess数据访问层,将默认的Class1.cs 改为DataAccess.cs,输入以下代码:
using  System;
using  System.Data;
using  System.Data.OleDb;
using  DALFactory;

namespace  DataAccess
{
    
public  class  DAOAccess:IDataAccessObject
    {
        
private  const  string  strConn  =  @" Provider = Microsoft.Jet.OLEDB.4.0;Data Source=D:"SHS_Develop"Solution"DB"Solution.mdb " ;

        
#region  IDataAccessObject 成員

        
public  void  Query(System.Data.DataSet ds,  string  strTableName)
        {
            
string  strSql  =  @" Select * From Employee " ;
            
using  (OleDbConnection Conn  =  new  OleDbConnection(strConn))
            {
                
using  (OleDbDataAdapter adapter  =  new  OleDbDataAdapter(strSql, Conn))
                {
                    adapter.Fill(ds, strTableName);
                }
            }
        }

        
public  void  Save( string  strBS_NO,  string  strBS_NAME)
        {
            
string  strSql  =  @" Insert Into Employee(BS_NO,BS_NAME) Values(@BS_NO,@BS_NAME) " ;
            
using  (OleDbConnection Conn  =  new  OleDbConnection(strConn))
            {
                
using  (OleDbCommand Comm  =  new  OleDbCommand(strSql, Conn))
                {
                    Comm.Parameters.Add(
new  OleDbParameter( " @BS_NO " , OleDbType.VarChar, 10 ));
                    Comm.Parameters.Add(
new  OleDbParameter( " @BS_NAME " , OleDbType.VarChar,  10 ));
                    Comm.Parameters[
" @BS_NO " ].Value  =  strBS_NO;
                    Comm.Parameters[
" @BS_NAME " ].Value  =  strBS_NAME;
                    Conn.Open();
                    Comm.ExecuteNonQuery();
                    Conn.Close();
                }
            }
        }

        
#endregion
    }
}

    展开Business层,将Class1.cs改为:BusinessLogic.cs,输入如下代码:
using  System;
using  DALFactory;

namespace  Business
{
    
public  class  BusinessLogic
    {
        
public  void  Query(System.Data.DataSet ds,  string  strTableName)
        {
            (
new  GetDatabaseType()).GetDatabase().Query(ds, strTableName);
        }

        
public  void  Save( string  strBS_NO,  string  strBS_NAME)
        {
            (
new  GetDatabaseType()).GetDatabase().Save(strBS_NO, strBS_NAME);
        }

    }
}

    最后,展开WinFrom层,在窗体上拖一个DatagridView、两个label,两个textBox和两个button过来,Name属性分别改为:FrmMain、dgvMain、tbxBS_NO,tbxBS_NAME,btnQuery,btnSave,输入如下代码:
using  System;
using  System.Collections.Generic;
using  System.ComponentModel;
using  System.Data;
using  System.Drawing;
using  System.Text;
using  System.Windows.Forms;
using  Business;
using  RealBusiness;
namespace  WinForm
{
    
public  partial  class  FrmMain : Form
    {
        
public  FrmMain()
        {
            InitializeComponent();
        }

        
private  void  btnQuery_Click( object  sender, EventArgs e)
        {
            DataSet ds 
=  new  DataSet();
            (
new  BusinessLogic()).Query(ds, " Employee " );
            
this .dgvMain.DataSource  =  ds;
            
this .dgvMain.DataMember  =  " Employee " ;
        }

        
private  void  btnSave_Click( object  sender, EventArgs e)
        {
            
if  ( ! RBEmployee.CanRegistUser(tbxBS_NO.Text))
            {
                MessageBox.Show(
" The Business Logic Can't Allow to Add this user  " );
                
return ;
            }
            (
new  BusinessLogic()).Save(tbxBS_NO.Text, tbxBS_NAME.Text);
        }
    }
}
    至此,可以说,一个简单的多层架构的Winform程序已完成,但如果有一些商业规则应如何加入呢,而且在现实世界中,商业规则是容易随宜主观的意愿而改变的。解决方法也是新加一个类。设为:RealBusiness层,class library模板,将Class1.cs改成:RBEmployee.cs,输入代码如下:
using  System;
namespace  RealBusiness
{
    
public  class  RBEmployee
    {
        
public  static  bool  CanRegistUser( string  strBS_NO)
        {
            
if  (strBS_NO.ToUpper()  ==  " ADMIN "  ||  strBS_NO.ToUpper()  ==  " ADMINISTRATOR " )
            {
                
return  false ;
            }
            
return  true ;
        }
    }
}
    好了,至此,一个多层架构已完整实现,虽然功能不是很强大,但对于多层架构也基本上全涉及到了。所谓麻雀虽小,五脏俱全。有兴趣的朋友可以随后下载全部源码。
    全部源码还实现了SQL Server的访问,由于Oracle没有用过,所以,在Oracle数据访问层中没有写任何代码,有会的朋友,请不吝回复在下面。先谢了。
    顺便说一下,下载源码后,双击Build_Access.bat将编译整个方案,你可以至Winform中Bin目录下运行方案的效果。该BAT将建立一个访问Access数据的多层Winform程序,相应的Build_Oracle.bat,Build_SQLServer.bat分别对应于oracle和sql server.

     Winform多层架构源码下载

    ps:
    欢迎各位加我QQ:52433739讨论,加时请注明C# Developer即可!

2007年3月14日又及:
   
    今天下班,重新对这个小Demo进行了一番审视检查,觉得这个实体放在这里怪怪没有起任何作用,查了一些书籍和资料,我决定将该Demo重新编写,所幸不负期望!
    确实,在这个小demo中,传递dataset是极不明确和含糊不清的,从而可能影响表示界面层的显示。为杜绝此类现象,终于发现了使用实体层的好处:那就是可规范所取得的数据的正确性。
    鉴于此,我个人就觉得DALFactory(数据访问层,工厂类)、Business(中间业务层)、WinForm(表示界面层)都需引用这个EntityReflect(实体层)。同样的,我在方案中将他们三个分别依赖于EntityReflect(实体层)。
    自然,相关的代码也将要进行修改,修改后的源码,请有兴趣的朋友请自行 重新下载。


posted on 2007-03-12 22:04 凯锐 阅读(6747) 评论(59)   编辑 收藏 网摘 所属分类: C# Programing 、 Design & Pattern

评论

 222.212.66.* 2007-03-13 09:06
写的不错
        

  2007-03-13 09:10  
结构清晰,通俗易懂.
不错!
          

  2007-03-13 11:00  
我很想实现WinForm下多层架构.可一直没有找到门路请指教....
          

  2007-03-13 11:05  
谢谢!好好研究一下,Windows Forms下多层开发是我这段时间比较关注的!有什么好的资料可以跟我分享,谢谢!!!
          

  2007-03-13 11:10  
博主是台胞吗?呵呵
          

 [楼主] 2007-03-13 11:44  
@teana
@若寒
謝謝﹗

@sunday
@Hsjtai
一起學習﹐共同進步﹗

@omnislash
不是啊﹐在港資企業上班。
          

  2007-03-13 13:43  
写的很好啊  能不能再多做几个关于分层的例子 再结合例子给点注释和说明!
          

  2007-03-13 13:46  
打印了下来,仔仔细细的看了一下,正是我想要的示范代码。
其中“考虑至数据库的可移槙性,数据访问层使用工厂模式,利用.net 的反射在运行时根据配置文件来动态决定采用何用数据库”部分,由于对反射不了解,所以DALFactory层的GetDatabaseType类的GetDatabase()方法及Business层(中间业务层)部分的代码不怎么懂!


          

 [楼主] 2007-03-13 13:58  
@badnewfish

這篇是我開始學多層時寫的。呵呵...




是當初學習多層時轉載的資料


          

  2007-03-13 14:22  
晕。。。。
兄弟,你传来传去不用领域模型来传数据,为什么还要实体层?

其实.net三层架构的例子很多,既然都是三层架构了,你还管他是不是winform的demo呢?webform也一样的道理,只不过把UI层换了而已。
所以,初学者可以去参考petshop。至少比看楼主这个例子有益得多。

当然,petshop离真正的多层应用还很远,这是后话了。。。。
          

 [楼主] 2007-03-13 15:12  
@Hsjtai
在C#中﹐RTTI(Runtime Type Identification)是能通過"反射"來實現的。它被封裝在“System.Reflection”命名空間下,通過C#反射﹐我們就可以在程序運行期間動態的建立對象。關于C#.NET反射﹐你可以到網上搜索一些資料來看看。
至于DALFactory的那段代碼﹐可以用自然語言解釋一下﹕
首先獲取配置文件中指定的程序集名稱和構造器名稱﹐
然后利用Assembly的Load()方法加載﹐并調用靜態方法CreateInstance()返回一個真實的對象實例。
          

 [楼主] 2007-03-13 15:14  
@yinh
誠然﹐我文章中也提及過
"不过,在我这个方案,我却一直没有在任何地方引用他。原因其实是我自己也不是很能弄清为什么一定要这个规范层。"
旨在求高手指點一二。
看兄弟好象很明白這點﹐能否指教一二。
          

  2007-03-13 16:17  
@旌浪
谢谢指教!
          

  2007-03-13 16:57  
与Petshop 类似
我也在学习中


          

  2007-03-13 19:08  
你所谓的实体,其实是领域模型,是我们从业务领域抽象出来的模型,我们所有的操作,其实都是在操作领域模型。
dataaccess层仅仅是负责领域模型的持久化操作。

在你的例子中,其实可以说是dataset是一个“领域模型”,因为你在所有的层之间,都是在传递这个所谓的dataset,但是你觉得这个dataset能表现出你的领域模型来吗?他oo吗?当然,在有些应用中,是直接用强类型化的dataset来做领域模型的,虽然我不喜欢这样。

你的业务逻辑层在操作什么?应该是在操作一个employee的对象或者其集合,你现在在操作什么?一个内存表?你应该对employee进行操作,而不是对empoyee表进行操作,如果是后者,那叫数据库处理程序,你包10层他也还是数据库处理程序。

当然,有些东西是用来平衡的,这话说来话长。

anyway,建议楼主好好去看看petshop吧,看懂了petshop,再往下走,petshop也仅仅是教你怎样从一个新手进入到自己动手写三层架构这个领域而已。它离真正成熟的多层应用还太远。随着你学习的深入,慢慢会懂的。
          

  2007-03-14 00:07  
我也纳闷呢,winform和webform不是就换了下表示层吗?业务逻辑层和数据访问层都没变化吧?那讨论"WinForm下多层架构"有什么特别之处吗?看来上面几位都是高手,请指教下二者的区别在哪呢?
          

 [楼主] 2007-03-14 08:35  
@yinh
受教了﹐謝謝﹗
          

 [楼主] 2007-03-14 08:45  
@Phinecos(洞庭散人)
只是表示層不一樣而已﹐我在文章開頭也表明了
"最近在CSDN上看到有朋友求Winform的三层架构的示例,网上也确实没有多少是Winform的。于是本人牺牲一点时间,做了这个小Demo,希抛砖引玉,望各路老手不吝指教。"
本人對三層架構中的實體也不能很是理解﹐所以覺得樓上yinh的確很好﹐特別是那几句
"但是你觉得这个dataset能表现出你的领域模型来吗?他oo吗?"很深刻﹗

不過﹐對于Petshop我倒真沒有仔細研究﹐看是看過﹐今晚回去研究一下﹐將該Demo再完善點。

繼續歡迎各位高手就WinForm下的多層架構發表高見﹐猶期是實體規范層該如何應用﹐謝謝﹗
          

  2007-03-14 10:19  
多数据库支持可以用ADO.NET2.0的DbProviderFactories模型来现实,不必自己写反射.
BusinnessLogic应该封装employee对象的各种商业操作吧.楼主的没有反应出这一点.
建议将模型单独抽象出一个项目:Model,这样更直观一点.
          

 [楼主] 2007-03-14 10:50  
@细节决定成败,习惯决定未来

商業規則﹐我將其放入RealBusiness层﹐原因是象這些商業規則﹐往往會隨客戶的主觀意愿而改變比較頻繁的。
比如說我上面的商業規則就假設不能注冊名為ADMIN,或ADMINISTRATOR的用戶﹐當然﹐至于這些算不算是商業規則﹐就要另當別論﹐或者說不同情況具體分析。

模型層是單獨分出EREmployee﹐但由于不是很明白如何應用﹐有何作用﹐所以在demo中并沒有引用。

至于ADO.NET2.0的DbProviderFactories模型﹐確實是現在才知道。受教了。
          

 219.133.80.* 2007-03-15 12:33
写得不错,楼主也好 好学呀! 加油!
        

 220.234.237.* 2007-04-03 16:37
支持楼主,谢谢了,十分感谢,希望还有更新的例子!

比别人只动嘴不动手强多了
        

 220.234.237.* 2007-04-03 20:21
楼主的GetDatabaseType.cs层
为什么更新之后里面没有代码
        

 220.234.237.* 2007-04-03 22:41
楼主,这句代码什么意思?谢谢
return (IDataAccessObject)Assembly.Load(strAssemblyName).CreateInstance(strConstractor, false);
        

 [楼主] 2007-04-04 08:36  
@Frank
首先謝謝你的支持﹐至于
return (IDataAccessObject)Assembly.Load(strAssemblyName).CreateInstance(strConstractor, false);的意思是﹕
首先獲取配置文件中指定的程序集名稱和構造器名稱﹐
然后利用Assembly的Load()方法加載﹐并調用靜態方法CreateInstance()返回一個真實的對象實例。
          

 220.234.237.* 2007-04-04 15:21
COOL!!

谢谢楼主!
我这两天一直分析楼主的实例呢,经典!除了感谢还是感谢+感谢!!
        

 220.234.237.* 2007-04-04 16:24
@旌浪
List lst = new List()
这句话什么意思?是用的泛型吗?
不过,泛型不是List lst=new List()吗?
你怎么直接把T给指定成EREmployee了?
        

 [楼主] 2007-04-04 17:50  
@Frank

沒錯啊﹐就是泛型﹐T可理解為只是一個占位符而憶﹐詳細信息你可以查閱一下msdn。
          

 220.234.237.* 2007-04-04 18:08
@旌浪
谢谢,认你当师傅了!:P
        

 [楼主] 2007-04-05 08:51  
@Frank

呵呵...
相互學習﹐共同提高。
          

 220.234.237.* 2007-04-06 11:25
代码我无法正常运行
错误位置:return (IDataAccessObject)Assembly.Load(strAssemblyName).CreateInstance(strConstractor, false);

错误信息:未能加载文件或程序集“DataAccess”或它的某一个依赖项。系统找不到指定的文件。

我已经把你代码里的ACCESS数据库位置更新了当前位置了
        

 220.234.237.* 2007-04-06 11:42
@Frank

是脚本问题,呵呵,搞定
        

 220.234.237.* 2007-04-07 13:01
我把我的管理系统改成楼主为主导思想的三层架构了!
确实,给我一种新的思维,想法!

但是,我忽然发现楼主的Business层基本没什么用,都是界面调用函数,然后它再去调用IDataAccessObject数据对象中的函数,此外我没想明白这个层还有什么用?

看看我写的这个层:
namespace Business
{
//商务逻辑层
public class BusinessLogic
{
IDataAccessObject DAObject;//数据库对象

public BusinessLogic()
{
DAObject = (new GetDatabaseType()).GetDatabase();
}

//学生注册
public void Register_Student(Student stu)
{
DAObject.Register_Student(stu);
}

//获取专业表
public DataSet GetDataSetMagors()
{
return DAObject.GetDataSetMagors();
}
//获取班级表
public DataSet GetDataSetClass(int Magor_ID)
{
return DAObject.GetDataSetClass(Magor_ID);
}
//增加专业
public void AddMagor(string MagorName)
{
DAObject.AddMagor(MagorName);
}
//删除专业
public void DeleMagor(int MagorID)
{
DAObject.DeleMagor(MagorID);
}
//增加班级
public void AddClass(int MagorID, string ClassName)
{
DAObject.AddClass(MagorID, ClassName);
}
public void DeleClass(int ClassID)
{
DAObject.DeleClass(ClassID);
}

public DataSet GetLesson(int Magor_ID)
{
return DAObject.GetLesson(Magor_ID);
}
}
}
        

 218.189.73.* 2007-04-07 15:07
@Frank
我的demo隻是一個演示,多層架構隻是便於今後你的程序的維護等,比起速度來,可能還不能你沒分層前。你說的沒錯,你完全可以不用分層,直接使用胖客戶端也可以寫出至少交貨當初較完美的程式出來的。至於你的代碼隻是在構造中先實例化了一下而已,跟我之前的是沒有多少分別的。
        

 220.234.237.* 2007-04-07 15:35
@旌浪

我明白的,但是我只是在想,Business层只写这点东西吗?是不是还能有别的用处呢?而只单纯的调用IDataAccessObject,没有什么非常重要的存在意义呀?想不明白
        

 [楼主] 2007-04-09 09:00  
@Frank
分層的目的之一就是將數據層與表示層合理的分隔﹐也就是說多層結構就像多個人共同完成一項工作,分別不同負責各自的工作。該知道自己知道的,不該知道自己不知道的。別八卦,別打聽不該自己知道的事。
請參閱﹕


          

 116.24.2.* 2007-08-22 16:48
暈,咋我在GetDatabaseType.cs中用時
return (IDataAccessObject)Assembly.Load(strAssemblyName).CreateInstance(strConstractor, false);報錯
        

 218.104.48.* 2008-02-25 13:05
--引用--------------------------------------------------
旌浪: @yinh
誠然﹐我文章中也提及過
"不过,在我这个方案,我却一直没有在任何地方引用他。原因其实是我自己也不是很能弄清为什么一定要这个规范层。"
旨在求高手指點一二。
看兄弟好象很明白這點﹐能否指教一二。
--------------------------------------------------------
试想一下如果没有实体规范层,表示层直接使用数据库字段
绑定数据显示Databinder.Eval ,如果修改了数据库对应的字段,
是不是还要修改表示层,
数据库架构的变化会一直影响到 ASPX 了
貌似代码听起来不太像 N 层了。

        

 [楼主] 2008-02-25 14:06  
@linuxjava01
我覺得你可能並沒有完全看完這篇文章,第一次寫這篇文章的時候,我確實沒有把實體層應用起來,但最后,聽取了@yinh 的建議之后,我就改變了SourceCode的呀!
如果說改變數據庫架構,你不改程序是不可能吧的 ? aspx是改動,改實體層難道就不算改動了嗎?呵呵...

          

 222.92.75.* 2008-03-05 14:27
@旌浪
楼主,你好。
我在运行这个语句:
return (IDataAccessObject)Assembly.Load(strAssemblyName).CreateInstance(strConstractor, false);
时,出现以下警告:
Could not load file or assembly 'DataAccess' or one of its dependencies. 系统找不到指定的文件。
我该怎么办啊?
我用的数据库是server 2000,

PS:我是新手,才接触ado.net一个星期,问题可能比较简单,不过对我还是有点困难,请帮忙指教下。
        

 116.30.136.* 2008-03-05 19:23
@Jeromelin
从错误提示也可以看出来,你的DataAccess.dll没有放在运行目录下。
你可以运行下载的代码中的脚本来处理这个问题,或直接自己将这个dll复制进运行目录下即可.
        

 222.92.75.* 2008-03-06 17:22
是这个Purge.vbs 脚本吗?
我已经运行了,可是当我输入数据时,还是出现那样的警告。
对于DAOSqlServer.cs和DAOAccess.cs这两个文件中的数据库位置也更新到了当前位置。


        

 202.173.244.* 2008-03-06 19:45
不是,說錯了,是批處理文件:如果使用Access數據庫的就運行
Build_Access.bat
另:不是將cs文件放在當前目錄,是dll放在當前目錄下。
        

 219.137.204.* 2008-03-06 23:06
谢谢
        

 222.92.75.* 2008-03-07 10:56
问题解决了,谢谢指点!!!
        

 222.209.203.* 2008-03-12 11:33
只是逻辑上的多层,不是物理上的多层?对于安全来说这种架构还不行!!!
        

 202.173.244.* 2008-03-12 13:49
@leexiaodong
可否指教一二......

        

 222.70.99.* 2008-03-28 15:37
源码中没注释啊!!
        

 202.173.244.* 2008-03-28 17:09
@不告诉你
你的名字特別,難不成我們認識?
開個玩笑,比較簡單,就沒有注釋,呵呵...
        

 123.149.21.* 2008-07-02 23:56
写的不错,正在学习。
        

 3.84.205.* 2008-07-21 15:08
return (IDataAccessObject)Assembly.Load(strAssemblyName).CreateInstance(strConstractor, false);

用了这句话,不是不能用混淆编译代码了?那不是没两天你的winform连源代码都给人猜解走了?
        

 [楼主] 2008-07-21 18:32  
@刀刀1
混淆代碼,本身也只是防君子,而難防小人的。呵呵...

          

 116.7.11.* 2008-10-21 16:29
只是dll,和winform放在同一台物理机器上,这是什么多层架构啊,晕!中间层一定要是部署在单独的应用服务器上,提供所有的客户端调用,这才是真正的多层结构!
        

 [楼主] 2008-10-21 18:52  
@yujiedu,
你說的是分布式的多層!我在這里並沒有指出這是一個分布式的多層架構。
從你的文字語氣來看,大有不屑一看的意思,所以.....你就當作沒有看到吧?
          

 222.212.21.* 2008-11-26 14:59
我也来说说,希望对大家有用。
首先多层属于架构层面的知识,为什么分层:在于职责分离、步暑易扩展、系统易扩充(如可把不同的层布暑至不同的服务器),开发分工协作。。。
一般我们会对解决方案分三层(如表现层、逻辑层、数据访问层),不同的层负责不同的职责,也可能由不同角色的开发人员来完成(如有些人强项在易用性、可操作性则可安排其做表现层;有些人在于属于该业务领域,则可安排其做领域层;有些人熟悉数据库,则可安排其数据访问层),再补充一点,很多人喜欢把数据库定义为数据访问层,其实不然,这点非常重要!
分层怎样分工呢?
1、表现层在于数据的收集和展现,关注重要的操作易用性、简洁美观性,但该层并不包括相应的业务逻辑,业务逻辑由逻辑层封装,具体业务逻辑是什么,怎么完成,对表现层的开发人员不知道也不需要知道(因为他只需要调用业务逻辑层类库而已,就当我们调用.Net框架类库一样)。
2、业务逻辑层,这层才是系统关注的重点,前期需求分析、设计基本上都基于该层而展开。一般又将该层分两个方面:服务层(用于表现层调用)和领域层(业务逻辑核心,并且不易改变)。领域层是所做系统的业务核心,用面向对象技术进行建模、分析和设计。所有设计类都针对该领域的一个系统关注点,有状态(字段、属性)有方法(完成相应领域逻辑),该类职责单一,并可和其他领域类共同完成相应逻辑(之间的关系当然是在分析时确定),这层习惯被人当作实体类。服务层完成其他相应逻辑(如事务控制、日志记录、组织业务功能点、完成数据持久化)。所以服务层其他调用的是领域层(完成领域逻辑)、数据访问层(完成数据持久化)、基础层(事务控制、日志记录)、组织业务功能等,这块即所谓易变部分(也可用抽象的做法,利用相应设计模式进行变化点封装,但更多的业务抽象在领域层)。服务层主要提供给表现层调用。
3、数据访问层,该层主要完成数据持久化任务,即把收集的数据保存至数据库(内存、文件、关系型、对象型),也从数据库中提取相应数据重新构造成领域对象。数据访问层主要提供给服务层调用,并不和领域层产生依赖(领域层可单独进行单元测试)。很多人写程序喜欢用存储过程进行业务逻辑处理,这也是很多人把数据库当成数据访问层的原因,业务逻辑放至存储过程的做法非常不利用系统扩展和抽象,面向对象解决的是复杂业务逻辑的处理,而关系型数据库根本达不到这种抽象的提取、变化的封装。
还有就是这种结构分层也利于代码复用,如想从B/S结构改为C/S结构,除了表现层改成WinForm外,其他任何层都可重用(最关键的是业务逻辑重用),只是给用户的展现变换了一种方式而已。
就说这么多吧,希望能对大家有用,也希望和大家继续交易。
        

 222.212.19.* 2008-11-26 15:18
再说说多层方面的误区吧。
很多人都知道多层,但其实对多层的好处和价值认识并不深,我曾和一个开发人员讨论多层时,他最后说:太麻烦了,设计类大多,之间调用太复杂,一会儿从这个类转到另一个类,另一个类又转向另一个类,头都搞昏了。
这其实就是典型的不知多层意义所在,甚至有人为了所谓的多层而多层,最主要的目的:职责分离、系统步暑扩展根本未达到。
现在团队都是一个分工协作合作的队伍,没有人能全部做完或精通所有的东西,这方面是你的强项,相对另一方面可能则是你的弱项。所以一个团队要有战斗力,肯定是把合适的人安排在合适的角色上,用他最强去攻战一个点。分层就样这个做法,不同的人做不同的事。比如我们装修房子,做水泥工的不会去做木工活,做电工的也不会去做水泥工的活,但大家分工合作,最后把一个新房给装修得非常完满。
我们做系统一样,你做表现,他做服务和逻辑、另外的人做数据访问,最后大家组织起来就是一个灵活、易用、易于扩展的良好系统。哪个地方出问题也能找到相应的责任人。
        

 [楼主] 2008-11-27 09:07  
@昌明.NET
分析的好,贊一個!
          

  2009-01-03 11:36  
好像没有实现ORM映射哦,实体层的作用就是做一个orm映射,之后访问的不在是dataSet,DataTable,而是一个个具体的对象了。
          

  2009-01-03 11:39  
昌明.NET [未注册用户] 分析的透彻,赞一个。
          

转载于:https://www.cnblogs.com/chenbg2001/archive/2009/01/23/1380334.html

你可能感兴趣的:(WinForm下多层架构的实现)