设计模式——一个会让很多人觉得高大上的名词。
实际上,设计模式并没有什么高深的知识在里面,它只是一种思想,使用这种思想,可以使得你的系统更容易被更新、维护,尽可能得避免了所谓的”动一发触全身“的被动状态。
我们把上面的话反过来看一下,就变成另一个意思了:
我们尽可能得使得系统变得容易更新、容易维护,我们使用各种办法使得”动一发触全身“的被动状态发生率降至最低的思路,就是设计模式的原出发点了。
关于设计模式的文章,网络上也是大把大把的,一般都会按照它们总结出来的各种模式一一介绍,比如用一篇文章介绍一下工厂模式(公认最简单的模式)。
但是我不认为设计模式是真有着明显的这个或者那个模式,而是一种思想,只要使用到了,就是好的。
我将顺着”什么是接口”,这系列的教学,带大家正式进入“设计模式”的教学篇,在这里,我们不是生硬得将设计模式拆开后一个一个讲解。而是将分析的思路慢慢溶入每一行代码中,自然而然的形成了各种设计模式。
首先,我们来看看这个例子:
对于一个做过几个项目的人来说,让他们去完成任何平台(窗体、网页等)上的登录行为,那是太容易不过的事了。
他们的思路肯定是这样的:
1、一个方法:接受参数 用户名,密码
2、拿这两个参数拼一个SQL语句
3、判断是否有查询结果
3-Y、记录下用户ID(以备后用),再加上一些其它操作,跳转窗体、页面,登录完成
3-N、提示用户”用户名或密码错误“
“很好,这样就完成了,太简单不过了” —— by 无名的程序员
唔,确实,从功能上来说,确实完成的非常好
然后我们来假设一些可能会遇到的情况:
1、要求单点登录,即一个用户不可以登录两次
“这好办,在判断登录成功后,再加一堆代码,判该这个用户ID是否在线,如果不在线才可以登录;如果在线提醒他” —— by 无名的程序员
唔,很轻松地解决了这个问题,很好。我们继续
2、你的上司希望这个单点登录是个可选的逻辑
"这依然简单,在配置文件写一个开关,在(1)添加的代码前加判断,小轻松~~" —— by 无名的程序员
唔,解决的很漂亮,以后只要改改配置文件,什么都不是问题了
3、项目越做越大,不光有窗体,还有网站,还有手机,我们不能一个一个写登录了,需要统一一个WebService控制所有程序
"唔,这次我学乖了,还是先做一个配置开关吧,顺便把WebService的URL也存进去,表示是否使用统一登录机制,然后利用分支来进行不同的登录流程" —— by 有长进的无名程序员
不得不说,变厉害了。
4、由于重大版本的更新,表结构变了……
5、由于重大版本的更新,WebService协议变了——
6、登录流程出现了BUG
"哎呀,登录流程有这么多分支,到底哪出BUG了" —— by 抓头的无名程序员
随着产品的不断提升,需求在变,功能也在变,堆着一堆配置项和一堆switch代码,时间久了,自己都不一定能管理好这些思路,更不要说,这只是登录。
现在我们设想一下:
我们现在站在一个豪宅的大门口,我们想进去 —— 登录
我们只需要给门卫看一下脸、报一下名字、出示一下门卡 —— 用户名 + 密码
门卫去后面干了些你不知道的事情 —— 登录流程
门卫告诉你可以进、或是不可以进 —— 登录结果
有没有发现一个很关键的事情? —— 登录流程我们不关心
对我们手上的这段代码来说,最关心的是如果登录成功干什么,如果登录失败干什么。
至于如何验证,按理说,不是这时候考虑的,应该有一个专门的"东西"负责这件事,至于这个东西怎么完成的,和我没关系。
这个概念,恰恰好与接口想吻合 —— 一个只提供了方法签名、属性、事件,但不去实现其功能的最抽象的类型
public interface ILoginChecker { bool Login(string loginName,string password); }
在你的代码中只需要声明一个ILoginChecker成员,并通过构造函数来决定它的具体类型,在程序中直接使用它即可。
public class LoginWindow : Form { private ILoginChecker loginChecker; public LoginWindow(ILoginChecker chcker) { this.loginChecker = chcker; } void LoginButton_Click(object sender, EventArgs e) { string loginName = null, password = null; //从控件上取值 //判断空值 //等一切OK时 if (this.loginChecker.Login(loginName, password)) { //登录成功 } else { //登录失败 } } }
我们来总结一下思路,把不关心的、可变的、可调整、可维护的内容,先不去实现,写成一个接口,直接使用这个接口上的方法,并把接口的填充交给构造函数(这一步不是必须)
我们把这个思路叫作 —— "控制反转",简称IOC
控制反转,是在大型项目中最常见存在的一种模式。Java中最有名的框架Spring其核心就是一个控制反转容器。
本次介绍的只是控制反转中最核心的思想,示例代码尚不能作为一个优秀的控制反转示例。
文章为作者原创,转载请注明出处,谢谢 http://www.cnblogs.com/ShimizuShiori/p/4923427.html