作为大话设计模式中唯一只有一个类的设计模式——单例模式,它是怎么来的呢?
首先,得区分一下,单例模式是面向对象语言中出现的。面向对象语言实际上就是针对对象来编程,对象抽象出类,再抽象就是接口和抽象类。它与面向过程的编程方式不同。具体不同点看下面的小例子一:
一、
先定义好一个登录窗体frmLogin,一个测试窗体frmTest,测试窗体frmTest中创建一个按钮btnLogin。点击按钮,调出登录窗体。
下边是按钮btnLogin的click事件里的两种调用代码:
1. <span style="font-size:18px;"> '第一种:面向过程的,把窗体直接使用 2. frmLogin.Show() 3. 4. '第二种:面向对象的,把登录窗体当做类来使用,调用的时候先实例化 5. Dim frmLogin1 As New frmLogin 6. frmLogin1.Show()</span>
第一种方法,按钮点击多次,只出现一个窗体。
但是它不是面向对象语言编程的思想,不予参考。
第二种方法,按钮点击多次,对应出现多个窗体。
二、
对应第二种方法,就出现一个问题——超生。我只需要一个窗体,但是却出来了这么多窗体。怎么解决呢?
我们可以在测试窗体里先声明一个全局变量frmLogin2,当我们在点击按钮btnLogin时,先进行判断,看frmLogin2是否已经实例化了。
1. <span style="font-size:18px;">Public Class frmTest 2. Private frmLogin2 As frmLogin '定义一个frmLogin类型的对象 frmLogin2 3. 4. Private Sub btnLogin_Click(sender As Object, e As EventArgs) Handles btnLogin.Click 5. 6. If frmLogin2 Is Nothing Then 7. '第三种:面向对象的,把登录窗体当做类来使用,调用的时候先实例化 8. frmLogin2 = New frmLogin 9. frmLogin2.Show() 10. End If 11. End Sub 12. End Class</span>
跟第二种方法相比,它就解决了相应的问题。
三、
不过,现在的代码还不够完善,又出现了新的问题,即点击一次btnLogin按钮之后,调出了登录窗体frmLogin,关掉它,再点击一次btnLogin按钮,登录窗体没办法出现了。
这是因为实例化了一次全局变量,关闭窗体,vb.net的垃圾自动回收机制没有把全局变量frmLogin2给回收,内存中还存在它的值,也就是它现在还是被实例化的状态。因此不能进行第二次实例化。这个问题也好解决——在判断条件里增加一个条件,frmLogin2是否被释放。
1. <span style="font-size:18px;"> If frmLogin2 Is Nothing Then 2. '第三种:面向对象的,把登录窗体当做类来使用,调用的时候先实例化 3. frmLogin2 = New frmLogin 4. frmLogin2.Show() 5. Else 6. If frmLogin2.IsDisposed = True Then 7. frmLogin2 = New frmLogin 8. frmLogin2.Show() 9. End If 10. End If</span>
如此,多个弹出框的问题以及关闭了就弹不出来的问题就解决了。
四、
这样就可以了吗?还不够~~~
我在菜单栏里添加一个菜单,也要实现调出登录窗体的功能,那么两份一样的代码就出现了。分别出现在btnLogin的click事件和menuLogin的click事件里。假如有十个地方要调用登录窗体,那么就会有十份相同的代码。一旦要修改,就要修改十个地方,代码的可维护性就下降了。怎么办呢?
我们是面向对象编程的一个重要思想就是抽象!重复的东西就给它抽象出来,以便重复使用。在这里就可以把btnClick里边的东西抽象出来到一个方法里。
1. <pre class="vb" name="code"><span style="font-size:18px;">Public Class frmTest 2. Private frmLogin2 As frmLogin '定义一个frmLogin类型的对象 frmLogin2 3. 4. Private Sub btnLogin_Click(sender As Object, e As EventArgs) Handles btnLogin.Click 5. Call Login() 6. End Sub 7. '第四种:把重复的功能代码抽象到方法里,直接调用 8. Private Sub Login() 9. If frmLogin2 Is Nothing Then 10. frmLogin2 = New frmLogin 11. frmLogin2.Show() 12. Else 13. If frmLogin2.IsDisposed = True Then 14. frmLogin2 = New frmLogin 15. frmLogin2.Show() 16. End If 17. End If 18. End Sub 19. End Class 20. </span>
五、
还是那句话,现在的代码够好了吗?依旧不够~~~
这个方法本是控制登录窗体的实例化,那么它的代码却写在了测试窗体里,这样好吗?自己的事情自己干,单一职责原则。因此,单例模式要登场了。
多谢赏阅,后续请看下回分解,让我们在追求完美的道路上越来越远吧。