说到外观模式,更是在个人重构中设计到的外观模式,我和好多人交流过这个问题,起初我是这么任性的认为:外观模式就是传递参数的,解耦B层和U层的关联。以至于刚开始我还和师傅就此问题而讨论,回来又看设计模式,还是不大懂外观到底起什么作用?直到最近敲上下机,才决然发现,自己理解的偏差。
先回忆一下外观模式在设计模式中介绍:
外观模式(Façade),为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。换句通俗易通的话:外观的引入,使得界面设计层不知道B层的存在,通过外观高层接口直接实现自己想要的功能。
【1】设计模式中外观模式:
1·下面先看一下外观模式类图:
2·代码实现部分:
客户端实现代码:
- Class Facade
- {
- SubSystemOne one;
- SubSystemOne two;
- SubSystemOne three;
- SubSystemOne four;
- Public Facade()
- {
- one = new SubSystemOne();
- two =new SubSystemTwo();
- three = new SubSystemThree();
- four = new SubSystemFour();
- }
- //方法A中只是封装了one,two,four的方法。
- Public void MethodA()
- {
- console.WriteLine("\n方法组A()----");
- one.MethodOne();
- two.MethodTwo();
- four.MethodFour();
- }
- //方法B只是对two,three两个方法的封装。
- Public void MethodB()
- {
- console.WriteLine("\n方法组B() ----");
- two.MethodTwo();
- three.MethodThree();
- }
- }
结合类图和代码:我们可以看出
- static void Main(string[] args)
- {
- Facade facade = new Facade();
- //由于Facade的作用,客户端可以根本不知道四个子系统的存在。
- facade.MethodA();
- facade.MethodB();
- console.Read();
- }
外观的方法A和方法B,方法A对子类中1,2,4方法进行统一封装,而方法B对子类中2,3方法进行了封装,也就是说这个外观中想要实现的功能用到哪个小功能,就可以对其封装。 客户端只是调用了外观的两个方法,而它根本不知道子类中MethodOne等方法的存在,这样,外观就起到了一个“接口”的作用,如果像我当初说的:外观仅仅是给界面层传递B层的返回值,那又有什么真实意义?
【2】对比于机房中用到的外观模式(以上下机为例):
(首先声明一点:我在实际做的时候子类中的方法不是这样划分的,只是这样更有对比性,其实道理都是一样的)对比于外观模式的类图,你会发现,这都是一样的东西,对不对。在上机过程中,我们要先进行一系列的判断。1.判断卡号是否存在
2.判断卡号是否注销
3.判断卡号余额是否大于最少上机金额
4.判断该卡号是否正在上机
如果没有外观,那这些功能就要一一在B层逻辑代码中体现,可是如果加入外观,直接在OnlineCheck方法中对这些小功能进行统一封装,也就是说,当在U层调用OnlineCheck方法时,这些功能就全部执行了,一项不符合,则直接跳出函数过程。
在下机的过程中,除了第3条不用判断以外,其它都要一一判断,这样的话,就不能调用OnlineCheck方法了,所以,在外观类中加入OfflineCheck方法,对1,4进行封装,然后在U层的下机单击事件中调用OfflineCheck方法。这样就达到真正的“解耦”目的,减少了U层和B层之间的依赖关系。
以一部分外观代码示例:
部分代码可能有些多余,但是大致理念都是一样的。整体设计模式中学习的外观模式和个人重构中用到的外观模式对比起来学习,其实会发现,外观模式也不过如此,真正用到实际中,自己的理解就会更为深刻一些。
- Imports Entity
- Imports BLL
- ''' <summary>
- ''' 该类用于在上机时,检查卡号是否存在,是否注销,余额是否大于最小限度,
- '''
- ''' </summary>
- ''' <remarks></remarks>
- Public Class FacCheckCard
- Public Function CheckCard(enStudent As Entity.StudentEntity) As Boolean
- Dim enBasicData As New Entity.BasicDataEntity
- Dim limitMoney As New BLL.SetBasicDataBLL()
- Dim check As New BLL.PublicBLL()
- Dim isOnline As New BLL.QueryRecordBLL()
- Dim mylistData As List(Of BasicDataEntity)
- Dim isRight As Boolean
- Dim mylist As List(Of StudentEntity)
- Dim enOnline As New Entity.OnlineEntity
- isRight = check.CheckCard(enStudent)
- If isRight = True Then '如果该卡号存在
- isRight = check.CheckStatus(enStudent)
- If isRight = True Then '如果该卡号没有注销
- mylist = check.CheckBalance(enStudent)
- mylistData = limitMoney.DataRecord(enBasicData)
- If Int(mylist(0).balance) < Int(mylistData(0).limitMoney) Then '判断上机余额是否大于最低限额
- MsgBox("余额小于最少上机余额" & Trim(mylistData(0).limitMoney) & "元")
- Return False
- Exit Function
- Else
- Return True
- End If
- Else
- MsgBox("该卡号已经注销!核实后再上机")
- Return False
- Exit Function
- End If
- Else
- MsgBox("该卡号不存在,请核实后再上机")
- Return False
- Exit Function
- End If
- End Function
- End Class
目前我理解的外观是这样的。还有哪里想的不周到的地方,还望多多交流沟通。