戏说面向对象程序设计(C#版) 第十三章 有了门面,程序员的程序会

第十三章    有了门面,程序员的程序会更加体面 织梦好,好织梦

 

本文来自织梦

大鸟说道:“实际上没有学过设计模式去理解三层架构会有失偏颇的,毕竟分层是更高一级别的模式,所谓的架构

copyright dedecms

模式。不过在程序中,有意识的遵循设计原则,却也可以有效的做出好的设计。” 织梦内容管理系统

      “不要告诉我,刚才讲的‘迪米特法则’就会在分层中用得上?”小菜说。

dedecms.com

      “当然用得上,否则讲它干吗,你当我是在安慰你而临时编个法则来骗骗你呀?来,再来看看你上次写的代码。” copyright dedecms

private    voidForm1_Load(objectsender,    EventArgse) dedecms.com

{

织梦好,好织梦

//读配置文件 dedecms.com

    ds =   new         DataSet(); 织梦内容管理系统

    ds.ReadXml(Application.StartupPath +     "\\CashAcceptType.xml");

内容来自dedecms

//将读取到的记录绑定到下拉列表框中 织梦内容管理系统

foreach(DataRowViewdr  inds.Tables[0].DefaultView)

织梦好,好织梦

    { 内容来自dedecms

        cbxType.Items.Add(dr["name"].ToString());

dedecms.com

    } copyright dedecms

    cbxType.SelectedIndex = 0; dedecms.com

} 内容来自dedecms

        “这是Form_Load的代码,里面有没有什么与界面无关的东西?”大鸟问道。

织梦内容管理系统

        “第4、5行是读配置文件的代码,它应该属于DAL层。对吧?”

copyright dedecms

      “很好,再看下面的这段,里面又有哪些呢?” 织梦内容管理系统

  copyright dedecms

private    voidbtnOk_Click(objectsender,       EventArgse)

织梦内容管理系统

{ 内容来自dedecms

    CashContext cc =  newCashContext();

dedecms.com

//根据用户的选项,查询用户选择项的相关行

copyright dedecms

DataRowdr = (

织梦内容管理系统

        (DataRow[])ds.Tables[0].Select("name='"+ cbxType.SelectedItem.ToString() +

织梦好,好织梦

"'")

内容来自dedecms

        )[0]; 织梦内容管理系统

//声明一个参数的对象数组

织梦好,好织梦

object[] args =       null; 内容来自dedecms

//若有参数,则将其分割成字符串数组,用于实例化时所用的参数 copyright dedecms

if(dr["para"].ToString() !=              "") 内容来自dedecms

        args = dr["para"].ToString().Split(',');

dedecms.com

//通过反射实例化出相应的算法对象 织梦内容管理系统

    cc.setBehavior( 内容来自dedecms

        (CashSuper)Assembly.Load("商场管理软件").CreateInstance("商场管理软件."+  织梦内容管理系统

            dr["class"].ToString(),

织梦好,好织梦

false, BindingFlags.Default,        null, args,      null,    null)); dedecms.com

 

dedecms.com

doubletotalPrices = 0d;

本文来自织梦

    totalPrices = cc.GetResult(Convert.ToDouble(txtPrice.Text) * copyright dedecms

Convert.ToDouble(txtNum.Text)); dedecms.com

    total = total + totalPrices;

织梦内容管理系统

    lbxList.Items.Add( copyright dedecms

"单价:"+ txtPrice.Text + 

织梦好,好织梦

" 数量:"+ txtNum.Text +      " "+ cbxType.SelectedItem +  copyright dedecms

" 合计:"+ totalPrices.ToString());

织梦内容管理系统

    lblResult.Text = total.ToString();

本文来自织梦

}

copyright dedecms

      “这里3-13 行,是为确定哪种算法而创建CashContext 对象,其中用到了反射技术,为计算做准备。第16 行是真正 本文来自织梦

的计算打折价或返利,17-19 是界面显示的部分。所以应该把3-16 行都搬到BLL 层去。不过,我还有些疑问,这样做会

织梦好,好织梦

让配置文件的数据要先从DAL 转到BLL,再转到表示层,多麻烦呀,什么不直接表示层读DAL,它想要数据就去读DAL,

copyright dedecms

它想算结果就去请求BLL 处理?”

织梦内容管理系统

      “那是说明你没有真的了解什么叫迪米特法则,象你那样说,不就等于,你小菜又要认识小张,又要认识小李了,这

内容来自dedecms

不就耦合过度吗?本来你只需要认识一个人就可以了,这样依赖才会小呀!”

copyright dedecms

      “可是我就得在BLL 里写一个专门返回从DAL 里得到数据的方法,这个方法不属于现在的任何类,我就还得再写一 织梦好,好织梦

个类来做这种传声筒的角色。而且由于界面还要涉及到其它的类,如CashContext,感觉UI 和BLL 耦合还是很高。” dedecms.com

      “说得没错,你的确是讲到点子上了,由于表示层UI 需要与BLL 有两个类进行交互,这是很麻烦,不过前辈们就想

织梦内容管理系统

了了一个较好的办法,另一个设计模式,‘门面模式’(Facade)或叫外观模式”

dedecms.com

(以下源自吕震宇 博客)

织梦好,好织梦

门面模式要求一个子系统的外部与其内部的通信必须通过一个统一的门面(Facade)对象进行。门面模式提供一个高层次 dedecms.com

的接口,使得子系统更易于使用。

织梦好,好织梦

  dedecms.com

门面模式的结构

织梦好,好织梦

门面模式是对象的结构模式。门面模式没有一个一般化的类图描述,下图演示了一个门面模式的示意性对象图:

内容来自dedecms

织梦好,好织梦

  织梦内容管理系统

在这个对象图中,出现了两个角色:

dedecms.com

 

dedecms.com

门面(Facade)角色:客户端可以调用这个角色的方法。此角色知晓相关的(一个或者多个)子系统的功能和责任。在正常

内容来自dedecms

情况下,本角色会将所有从客户端发来的请求委派到相应的子系统去。 本文来自织梦

  织梦内容管理系统

子系统(subsystem)角色:可以同时有一个或者多个子系统。每一个子系统都不是一个单独的类,而是一个类的集合。每 copyright dedecms

一个子系统都可以被客户端直接调用,或者被门面角色调用。子系统并不知道门面的存在,对于子系统而言,门面仅仅

本文来自织梦

是另外一个客户端而已。 内容来自dedecms

 

内容来自dedecms

        “哦,你这样一讲,我就明白了。”小菜说,“上篇所讲的IT 部,其实可以由部门主管就是门面,我们只需要找到部门

copyright dedecms

主管,就可以通过他安排相关的人来提供服务,我们不需要了解IT 部的具体情况了。” 本文来自织梦

        “其实现实中这样的例子很多。比如以前上海市没有新闻发言人,当要到春运时,所有的记者都跑到交通部去了解信

内容来自dedecms

息,当有非典或禽流感时,所有的记者又跑到卫生部去打听情况,突然这时候楼市大跌,记者们又得马不停蹄前往建设 本文来自织梦

部收集新闻。辛苦呀,有什么办法呢,吃这口饭的。但其实辛苦地又何止只是记者。各个政府部门都需要专人来应付这 织梦内容管理系统

些记者,不能多说话,不能说错话,但也不能不说话。也辛苦呀,谁叫他们是政府呢。”大鸟仿佛自己感同身受似的描述

copyright dedecms

着,“于是,新闻发言人横空出世,一位知识女性焦扬,代表上海市政府发言,从此,老记们不需要头顶骄阳奔跑于各大

内容来自dedecms

政府部门之间,只需要天天等在新闻发言厅门口守着就可以写出准确及时的新闻。而政府部门也不用专人来应付老记们 织梦好,好织梦

的围追堵截,有更多的时间为人民做实事办好事。这里就只辛苦一个人。”

织梦内容管理系统

      “那一定是新闻发言人自己了,因为她需要先与政府部门沟通好,要说些什么、如何说、如何回答刁钻问题。然后要 织梦好,好织梦

站在镁光灯下承受压力接受记者的访问。不过,干这一行就是需要辛苦的,这是政府的门面呀。”小菜感慨到。 内容来自dedecms

织梦内容管理系统

        “好了,去改写吧,你一定会感受到分层后代码的漂亮。”大鸟鼓励道。 copyright dedecms

过一小时后,小菜给出商场收银程序的第六份作业。。 内容来自dedecms

DAL 层代码(目前是读配置文件,以后可以很容易的修改为访问数据库) 内容来自dedecms

 

dedecms.com

usingSystem;

织梦好,好织梦

usingSystem.Collections.Generic;

copyright dedecms

usingSystem.Text; 织梦内容管理系统

usingSystem.Data;

copyright dedecms

 

本文来自织梦

namespace商场管理软件.DAL 内容来自dedecms

{ dedecms.com

public   class   CashAcceptType

织梦内容管理系统

    {

内容来自dedecms

public   DataSetGetCashAcceptType()

内容来自dedecms

        { 内容来自dedecms

//读配置文件到DataSet 本文来自织梦

DataSetds =   new DataSet(); 本文来自织梦

            ds.ReadXml("CashAcceptType.xml"); dedecms.com

returnds;

dedecms.com

        } 织梦内容管理系统

    }

本文来自织梦

}

织梦内容管理系统

BLL层主要代码(Facade类代码)

织梦内容管理系统

  dedecms.com

namespace商场管理软件.BLL copyright dedecms

{ 内容来自dedecms

public   class   CashFacade 织梦内容管理系统

    { 内容来自dedecms

const  stringASSEMBLY_NAME =     "商场管理软件.BLL"; dedecms.com

 

dedecms.com

//得到现金收取类型列表,返回字符串数组

copyright dedecms

public   string[] GetCashAcceptTypeList()

dedecms.com

        {

dedecms.com

            CashAcceptType cat =  newCashAcceptType();

dedecms.com

            DataSet ds = cat.GetCashAcceptType();

织梦好,好织梦

introwCount = ds.Tables[0].DefaultView.Count;

dedecms.com

string[] arrarResult =          new     string[rowCount];

织梦好,好织梦

  织梦好,好织梦

for(inti = 0; i < rowCount; i++)

copyright dedecms

            {

织梦好,好织梦

                arrarResult[i] = (string)ds.Tables[0].DefaultView[i]["name"]; 织梦内容管理系统

            } copyright dedecms

returnarrarResult; 内容来自dedecms

        }

copyright dedecms

  dedecms.com

/**/

织梦好,好织梦

///     <summary>

织梦内容管理系统

///用于根据商品活动的不同和原价格,计算此商品的实际收费 织梦好,好织梦

///     </summary> copyright dedecms

///     <param name="selectValue">下拉列表选择的折价类型</param>

内容来自dedecms

///     <param name="startTotal">原价</param>

内容来自dedecms

///     <returns>实际价格</returns>

织梦好,好织梦

public   doubleGetFactTotal(stringselectValue,         doublestartTotal) 织梦好,好织梦

        {

本文来自织梦

            CashAcceptType cat =  newCashAcceptType(); 织梦内容管理系统

            DataSet ds = cat.GetCashAcceptType(); 织梦内容管理系统

  dedecms.com

            CashContext cc =  newCashContext();

内容来自dedecms

            DataRow dr = (

织梦好,好织梦

                (DataRow[])ds.Tables[0].Select("name='"+ selectValue +           "'")

本文来自织梦

                )[0]; copyright dedecms

object[] args =       null; 织梦好,好织梦

if(dr["para"].ToString() !=              "") 织梦好,好织梦

                args = dr["para"].ToString().Split(','); 织梦内容管理系统

 

copyright dedecms

            cc.setBehavior(

内容来自dedecms

                (CashSuper)Assembly.Load(ASSEMBLY_NAME).CreateInstance 织梦内容管理系统

                (

本文来自织梦

                    ASSEMBLY_NAME +    "."+ dr["class"].ToString(), 织梦好,好织梦

false, BindingFlags.Default,        null, args,      null,    null

copyright dedecms

                )

织梦内容管理系统

                    );

copyright dedecms

returncc.GetResult(startTotal); 织梦好,好织梦

  本文来自织梦

        }

内容来自dedecms

    } 织梦好,好织梦

}

内容来自dedecms

  copyright dedecms

UI层代码(可以很容易的转换为Web页面) copyright dedecms

 

织梦内容管理系统

doubletotal = 0.0d;//用于总计

copyright dedecms

CashFacade cf = newCashFacade();

织梦内容管理系统

  织梦好,好织梦

private    voidForm1_Load(objectsender,    EventArgse) 织梦内容管理系统

{

内容来自dedecms

//读数据绑定下拉列表 dedecms.com

    cbxType.DataSource = cf.GetCashAcceptTypeList();

内容来自dedecms

  本文来自织梦

    cbxType.SelectedIndex = 0; dedecms.com

}

内容来自dedecms

 

copyright dedecms

private     voidbtnOk_Click(objectsender,            EventArgse)

本文来自织梦

{

织梦好,好织梦

doubletotalPrices = 0d; 本文来自织梦

//传进下拉选择值和原价,计算实际收费结果

织梦内容管理系统

    totalPrices = cf.GetFactTotal(

内容来自dedecms

        cbxType.SelectedItem.ToString(), 

copyright dedecms

Convert.ToDouble(txtPrice.Text) *        Convert.ToDouble(txtNum.Text)

织梦内容管理系统

        ); copyright dedecms

    total = total + totalPrices; 织梦好,好织梦

    lbxList.Items.Add( dedecms.com

"单价:"+ txtPrice.Text + 

织梦好,好织梦

" 数量:"+ txtNum.Text +      " "+ cbxType.SelectedItem +  织梦内容管理系统

" 合计:"+ totalPrices.ToString());

内容来自dedecms

    lblResult.Text = total.ToString();

dedecms.com

} copyright dedecms

项目文件结构图 dedecms.com

本文来自织梦

        “大鸟,来看看这下怎么样,还有没有可修改的地方?”小菜问道。

织梦好,好织梦

        “小菜开始谦虚了吗!以前不是一直信誓旦旦,现在怎么,没信心了?”

copyright dedecms

        “越学越觉得自己知道的少,感觉代码重构没有最好,只有更好呀。”小菜诚心的答道        。

dedecms.com

        “写得很不错。BLL 层的CashFacade 类其实就是新闻发言人,程序的门面;而应用程序或Web 其实就类似CCTV 织梦内容管理系统

和SMG,都是新闻单位,他们不应该也不需要关心门面后面的实现是如何的。             ,现在用了门面模式以后,耦合比以

本文来自织梦

前要少很多了,更改会更加方便,扩展也很容易了。你要是再回过头来看看最初的代码和现在的代码,你会体会更深刻,

织梦内容管理系统

更加明白重构的魅力。” 织梦好,好织梦

内容来自dedecms

  织梦内容管理系统

大鸟接着说:“之前的代码,下拉控件的绑定是硬编码,所以只要改动需求就得改代码,现在是读配置文件,大大 copyright dedecms

增加灵活性;之前的代码是根据用户选择,分支判断执行相应的算法,现在整个算法类全部搬走,做到了业务与界面的 织梦内容管理系统

分离;之前的代码由于全写在form 里,所以要更换成Web 方式,即C/S 改为B/S 非常困难,要全部重新写(注意真实

织梦好,好织梦

的软件系统不会这么简单,所以简单复制不能解决问题),现在的代码由于把业务运算分离,所以界面的更改不会影响 内容来自dedecms

业务的编写。还有就是现在的代码由于DAL 与BLL 分离,配置文件可以很容易的更换为数据库读取,且不需要影响表 dedecms.com

示层与业务逻辑层的代码。总的来讲,若是程序不会变化,原有的设计就没什么问题,运行结果正确足够了,但若是程 dedecms.com

序可能会时常随业务而变化,新的设计就大大提高了应变性,这其实就是应用设计模式的目的所在。”

内容来自dedecms

        “我现在越来越有信心学好它,设计模式真的很有意思,学它不学它,写出来的代码大不一样。老大,跟你混,看来

本文来自织梦

没有错。”

本文来自织梦

        “嗨,小菜,我不做老大已经很久了!”大鸟仰身长叹,扬长而去。

织梦内容管理系统

本文源代码。CashAcceptSystem4.rar

织梦内容管理系统

其中分四个项目,DAL、BLL、WebUI 和WinUI,可设置WebUI 和WinUI 为启动项目,注意由于只是学习源代码,配

内容来自dedecms

置路径没有做处理(实际应用需要config 文件),WebUI 配置文件CashAcceptType.xml 在“\商场管理软件06 分层\”根

copyright dedecms

目录下,而WinUI 的配置文件CashAcceptType.xml 在“\商场管理软件06 分层\商场管理软件\bin\Debug\”目录下。 织梦好,好织梦

精彩推荐
热点内容
最近更新