在机房重构之前,我们学习了设计模式,在这次重构中,我们的任务就是将这些模式,添加到机房的重构中去。现在先来解决一个最简单的问题——窗体的超生。
如果不加以限制,结果会是这样:
非常的不友好。那么我们如何来解决这个问题呢?——单例模式。
通常我们可以让一个全局变量使得一个对象被访问,但他不能防止你实例化多个对象,一个最好的办法就是,让类自身保存它的唯一实例,这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例的方法。
在这里有两种理解。一种正确的一种错误的。
首先把声明放到类的全局变量中,然后写一个判断是否实例化过的方法,当需要该窗体显示时,调用该方法。代码如下:(注册)
private frmRegister fr;//声明全局变量 private void btnRegister_Click(Object sender,EventArgs e) { openRegister(); } private void openRegister()//判断方法 { if (ftb==null || ftb.IsDisposed) { ftb =new FormToolbox(); ftb.MdiParent = this; ftb.Show(); } }很显然,这是一种面向过程的思维,窗体有没有被实例化,需要主窗体去判断,我们需要的是面向对象的思想。所以,这虽然可以实现单例模式的功能,但却不是单例模式。
同样,需要声明静态类变量,但是这次是在子窗体中声明的,然后构造一个私有的方法,外部代码就不能通过new来实例化它,也就是说只有该窗体才有资格实例化,最后在该类中写静态方法。代码如下:
Public partial class frmRegister:Form { private static frmRegister fr=null;//<span style="font-size:18px;">声明静态类变量</span> private frmRegister()//<span style="font-size:18px;">构造一个私有的方法</span> { InitializeComponent(); } public static frmRegister GetInstance()//静态的类方法,返回值就是该类的实例 { if (fr == null || fr.IsDisposed) { fr = new frmRegister(); fr.MdiParent = MDIfrmMain.ActiveForm; } return fr; } }这样,我们在客户端调用时,只需要写:frmRegister.GetInstance().Show();就可以了,客户端不用做任何工作,只是在需要的时候调用一下方法就可以了。而且外部不能通过new来实例化这个窗体,因为这个窗体只有一个实例化,被这个类自己保存着。调用方法时类会判断有没有被实例化过,如果没有,则实例化一个返回,如果有,则直接返回。
虽然第一种方法不符合面向对象,但是我为什么要写它呢?这就和我的机房有点关系。大家都知道,机房收费系统的主界面有一张图片,这就需要一个转换容器的api函数去做相应的转换,这样一来,单例模式在实际中的应用就要多点东西,也就是在每一个子窗体上都加上引用,然后在每个窗体中去做调换,我认为这是相当麻烦并且也不是一个好办法,所以,在反复比较下,我选择了之前相对错误的做法,将判断的权利交给主窗体。
一个模式的应用并不是死板的,在对的时候用对的模式,不拘泥于模式的格式,怎样使系统做起来更简单,更好用,就怎样做,活学活用,才是我们学习设计模式的目的。