子系统类软件设计模式系列之三 门面模式(也叫外观模式,Facade) .

题记:写这篇博客要主是加深自己对子系统类的认识和总结实现法算时的一些验经和训教,如果有错误请指出,万分感谢。

    我们接着上篇文章来讲,上篇最后将场商收银软件实确做到序程易维护,可展扩。但是,这样就完了吗?

    如果你的序程再也不修改了,或者就是改改打折的额度和返利额度,那么的代码是充足可以了。不过求需是却会断不生产的。比如说,在现这个序程是单机版的序程,如果须要场商多层楼的有所收银机都要用使,那该怎么办?
那用XML的配置文件就不适合了,该用应数据库会比较好。
C/S架构的处坏,新更费事,够不安全等等,他也不是傻瓜,每次新更都须要针对每台器机部署,一次就半天,那些工作时间他是须要给序程员付薪水的。所以他提出要改成B/S架构,客户端用浏览器持支,你怎么办?
那须要改界面了,把用应序程改成Web序程。

     

    “就你在现的代码,改起来轻易吗?”
“好象不轻易,须要新重写,尽管可以复制一些代码去过,不过要新重写的西东还是很多的。”
“好,那你有无发明,我说了这么多的求需动变,但系统中有一些西东直一没有变,是哪些?”
“晓得,是策略模式用到的那几个类,也就是畸形收费、打折费消、返利费消等法算是没有变更的。”

    “是呀,其实不是法算不会变,而是之前我们经已虑考它很多了,用了策略模式,用了射反术技使得它的变更绝对稳定。你刚才也说,要把用应序程改成Web是须要复制粘贴的,可事实上,改改界面和这些法算有什么关系?”
“没有关系。”
“还有,把配置文件改成数据库拜访,这实际上是读取写入数据的作操,和法算又有什么关系呢?”
“也没有关系,是说,他们之间完整可以分开离,互不影响,修改其一,不要影响其它两者?哦,这是不是就是所谓的三层架构?”
“所谓的三层发开,就是关于表示层、业务逻辑层和数据拜访层的发开。
这其实只是大方向的层分,每一个层中都有可能再细分为多个次层和构结。”

    

    

    既然要改成B/S构结,那么我们该应将本来的处置计分划为三个项目:
一个UI项目,现在是WinForm的序程
一个BLL项目,用来把法算类都装封
一个DAL项目,用来拜访配置文件

    这时,我们就不得不提到‘迪米特则法(LoD)’ 也叫少最知识准则。

    什么时候LoD呢?

    简略的说,就是如果两个类不必彼此直接通信,那么这两个类就不当应产生直接的相互作用。如果其中一个类须要调用另一个类的某一个方法的话,可以通过者三第转发这个调用。
实迪米特则法还是在讲如何增加合耦的问题,类之间的合耦越弱,越有利于用复,一个处在弱合耦的类被修改,不会对有关系的类成造及波。也就是说,息信的隐藏促进了软件的用复。

     

    

    对于我们之前的代码中,色红部份读取配置文件的代码他该应属于DAL层

    

    之前这段代码中,我们可以清晰的看到,蓝色该应属于BLL,也就是在业务逻辑层。色黑属于UI层,也就是在表示层。

    而我们希望的是,在表示层里头只要告知系统单价和数量,然后失掉结果就行。

    这就像是我们要去买个脑电,在现有2种计划:

    一个计划是,我们去电子市场把自己须要的配件都买回来,然后自己组装,也就是DIY(Do It Yourself)。

    

    另一个计划是,我们去找一家专业的装机公司,我详细的要求提出来,然后等着拿脑电就好了。

    

    第一个计划就相似我们之前做的序程,将UI,BLL,DAT 各个配件拿到一同,然后自己组装。

    第二个计划就相似我们在现希望的序程,我们需只告知系统单价和数量,系统返回我们结果就行。

    第二种计划中的这个专业的装机公司,其实就相当于我们本篇博文要讲的角主 门面模式(观外模式)

    什么是门面模式呢?

    简略的讲门面模式(也叫观外模式)要求一个子系统的外部与其部内的通信必须通过一个同一的门面(Facade)象对停止。门面模式供提一个高次层的接口,使得子系统更易于用使。

    也就相当于我们配机的第二个计划。

    当然事实生活中有很多这样的例子,比如CCTV可以道报医疗,育教等域领的息信。晨报也可以道报。对于他们获得的闻新,他们不可能直接去一个域领类为大家道报闻新,那么事实中他们是怎么让大家解了闻新的呢?对于CCTV的道报我们再熟习不过了,那就是天每7点的闻新,而闻新发言人就充当着门面角色(Facade),晨报的纸报充当着门面角色。面下2张图可以象形的说明这个情理。

    

    门面模式(也叫观外模式,Facade)

    1. 意图
为子系统中的一组接口供提一个致一的界面, Facade模式义定了一个高层接口,这个接口使得这一子系统更加轻易用使。
2. 念头
将一个系统分划成为若干个子系统有利于下降系统的杂复性。一个见常的计设目标是使子系统间的通信和相互赖依关系到达最小。到达该目标的门路之一是就是引入一个观外(facade)象对,它为子系统中较一般的施设供提了一个单一而简略的界面。

    3. 适用性

    1)当你要为一个杂复子系统供提一个简略接口时。
子系统常常因为断不化演而变得越来越杂复。大多数模式用使时都市生产更多更小的类。这使得子系统更具可重用性,也更轻易对子系统停止定制,但这也给那些不须要定制子系统的户用带来一些用使上的难困。
Facade可以供提一个简略的缺省视图,这一视图对大多数户用说来经已充足,而那些须要更多的可定制性的户用可以过越facade层。
2)客户序程与抽象类的实现部份之间存在着很大的赖依性。
引入facade将这个子系统与客户以及其他的子系统分离,可以进步子系统的独立性和可移植性。
3)当你须要构建一个次层构结的子系统时
用使facade模式义定子系统中每层的进口点。如果子系统之间是相互赖依的,你可以让它们仅通过facade停止通信,从而简化了它们之间的赖依关系。

    4. 构结

    

    5. 参与者

    • Facade ( Compiler )
— 晓得哪些子系统类负责处置求请。
— 将客户的求请理代给恰当的子系统象对。
• Subsystem classes ( Scanner、Parser、ProgramNode等)
— 实现子系统的能功。
— 处来由Facade象对指派的任务。
— 没有facade的任何关相息信;即没有向指facade的针指。
6. 协作

    • 客户序程通过发送求请给Facade的式方与子系统通信, Facade将这些息消转发给恰当的子系统象对。尽管是子系统中的有关象对在做事实工作,但Facade模式本身也必须将它的接口转换成子系统的接口。
• 用使Facade的客户序程不须要直接拜访子系统象对。
7. 效果

    每日一情理
生活的无奈,有时其实不源于自我,别人无心的筑就,那是一种阴差阳错。生活本就是矛盾的,白天与黑夜间的距离,春夏秋冬之间的轮回,于是有了挑剔的喜爱,让无奈加上了喜悦的等待。

    1) 它对客户屏蔽子系统组件,因而增加了客户处置的象对的数目并使得子系统用使起来更加便方。
2) 它实现了子系统与客户之间的松合耦关系,而子系统部内的能功组件常常是紧合耦的。
3) 如果用应须要,它其实不制约它们用使子系统类。因此你可以在系统易用性和通用性之间加以选择。
8. 实现

    1) 下降客户-子系统之间的合耦度
2) 大众子系统类与私有子系统类

    面下我们对于我们之前的场商收银系统停止我们希望的改良:

DAL层代码(现在是读配置文件,当前可以很轻易的修改成拜访数据库) 
using System; 
using System.Collections.Generic; 
using System.Text; 
using System.Data; 
namespace 场商管理软件.DAL 
{ 
	public class CashAcceptType 
	{ 
		public DataSet GetCashAcceptType() 
		{ 
			//读配置文件到DataSet 
			DataSet ds = new DataSet(); 
			ds.ReadXml("CashAcceptType.xml"); 
			return ds; 
		} 
	} 
}

    
这里期后我们完整可以用工厂模式来到达持支多种数据库。

BLL层要主代码(Facade类代码) 
namespace 场商管理软件.BLL 
{ 
	public class CashFacade 
	{ 
		const string ASSEMBLY_NAME = "场商管理软件.BLL"; 
		//失掉现金收取型类列表,返回字符串数组 
		public string[] GetCashAcceptTypeList() 
		{ 
			CashAcceptType cat = new CashAcceptType(); 
			DataSet ds = cat.GetCashAcceptType(); 
			int rowCount = ds.Tables[0].DefaultView.Count; 
			string[] arrarResult = new string[rowCount]; 
			for (int i = 0; i < rowCount; i++) 
			{ 
				arrarResult[i] = 									(string)ds.Tables[0].DefaultView[i]["name"]; 
			} 
			return arrarResult; 
		} 
		/// <summary> 
		/// 用于根据商品活动的不同和原价格,算计此商品的事实收费 
		/// </summary> 
		/// <param name="selectValue">下拉列表选择的折价型类</param> 
		/// <param name="startTotal">原价</param> 
		/// <returns>事实价格</returns> 
		public double GetFactTotal(string selectValue, double startTotal) 
		{ 
			CashAcceptType cat = new CashAcceptType(); 
			DataSet ds = cat.GetCashAcceptType(); 
			CashContext cc = new CashContext(); 
			DataRow dr = ( (DataRow[])ds.Tables[0].Select("name='" + selectValue + "'") )[0]; 
			object[] args = null; 
			if (dr["para"].ToString() != "") 
			args = dr["para"].ToString().Split(','); 
			cc.setBehavior( 
			(CashSuper)Assembly.Load(ASSEMBLY_NAME).CreateInstance( 
			ASSEMBLY_NAME + "." + dr["class"].ToString(), 
			false, BindingFlags.Default, null, args, null, null ) ); 
			return cc.GetResult(startTotal); 
		} 
	} 
}

    
 

UI层代码(可以很轻易的转换为Web页面) 
double total = 0.0d;//用于总计 
CashFacade cf = new CashFacade(); 
private void Form1_Load(object sender, EventArgs e) 
{ 
	//读数据绑定下拉列表 
	cbxType.DataSource = cf.GetCashAcceptTypeList(); 
	cbxType.SelectedIndex = 0; 
} 
private void btnOk_Click(object sender, EventArgs e) 
{ 
	double totalPrices = 0d; 
	//传进下拉选择值和原价,算计事实收费结果 
	totalPrices = cf.GetFactTotal( 
	cbxType.SelectedItem.ToString(), 
	Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text) ); 
	total = total + totalPrices; 
	lbxList.Items.Add( 
		"单价:" + txtPrice.Text + 
		" 数量:" + txtNum.Text + " " + cbxType.SelectedItem + 
		" 总计:" + totalPrices.ToString()); 
	lblResult.Text = total.ToString(); 
}

    

    我们可以对比下最原始的代码和我们经过好几次构重后的在现的代码,两段表示层的代码一样的简略,那么孰优孰劣呢?

    

    门面模式就给大家分析到这里吧,大家看到这里,该应或多或少有些收成了,软件计设模式,其实很多都是在我们事实发开过程当中遇到了问题,然后处置,然后总结出来的验经,所构成的模式。

    在现我们再将系列一计设模式的义定拿出来看看,计设模式是指在软件发开中经过证验的用于处置在特定环境重复涌现特定问题处置计划实确是这么回事。

文章结束给大家分享下程序员的一些笑话语录: 自行车
一个程序员骑着一个很漂亮的自行车到了公司,另一个程序员看到了他,问 到,“你是从哪搞到的这么漂亮的车的?”
骑车的那个程序员说, “我刚从那边过来, 有一个漂亮的姑娘骑着这个车过来, 并停在我跟前,把衣服全脱了,然后对我说,‘你想要什么都可以’”。
另一个程序员马上说到, “你绝对做了一个正确的选择, 因为那姑娘的衣服你 并不一定穿得了”。

原文地址:https://www.cnblogs.com/xinyuyuanm/p/3050687.html