单件模式Singleton来控制窗体被重复或多次打开
本文转载:http://blog.csdn.net/a0700746/article/details/4473796
一般在百度搜一下,会出来一下内容,看来很好用。Singleton很方便的一个用处就是控制窗体被多次或重复打开。下面是它的用法。
一般Singleton模式通常有几种形式:
public class Singleton {
private Singleton(){}
//在自己内部定义自己一个实例,是不是很奇怪?
//注意这是private 只供内部调用
private static Singleton instance = new Singleton();
//这里提供了一个供外部访问本class的静态方法,可以直接访问
public static Singleton getInstance() {
return instance;
}
}
第二种形式:
public class Singleton {
private static Singleton instance = null;
public static synchronized Singleton getInstance() {
if (instance==null)
instance=new Singleton();
return instance; }
}
使用Singleton.getInstance()可以访问单态类。
上面第二中形式是lazy initialization,也就是说第一次调用时初始Singleton,以后就不用再生成了。
注意到lazy initialization形式中的synchronized,这个synchronized很重要,如果没有synchronized,那么使用getInstance()是有可能得到多个Singleton实例。关于lazy initialization的Singleton有很多涉及double-checked locking (DCL)的讨论,有兴趣者进一步研究。
一般认为第一种形式要更加安全些。
使用Singleton注意事项:
有时在某些情况下,使用Singleton并不能达到Singleton的目的,如有多个Singleton对象同时被不同的类装入器装载;在EJB这样的分布式系统中使用也要注意这种情况,因为EJB是跨服务器,跨JVM的。
我们以SUN公司的宠物店源码(Pet Store 1.3.1)的ServiceLocator为例稍微分析一下:
在Pet Store中ServiceLocator有两种,一个是EJB目录下;一个是WEB目录下,我们检查这两个ServiceLocator会发现内容差不多,都是提供EJB的查询定位服务,可是为什么要分开呢?仔细研究对这两种ServiceLocator才发现区别:在WEB中的ServiceLocator的采取Singleton模式,ServiceLocator属于资源定位,理所当然应该使用Singleton模式。但是在EJB中,Singleton模式已经失去作用,所以ServiceLocator才分成两种,一种面向WEB服务的,一种是面向EJB服务的。
Singleton模式看起来简单,使用方法也很方便,但是真正用好,是非常不容易,需要对Java的类 线程 内存等概念有相当的了解。
总之:如果你的应用基于容器,那么Singleton模式少用或者不用,可以使用相关替代技术。
以下是本人在实际的项目中的具体灵活运用,希望能帮到大家的忙。
问题描述:用了单件模式Singleton来控制窗体被重复或多次打开,最初是在MDI子窗体中写方法,后来看别人的写的是属性,基本是一样的,都可以,然后想的是,项目中有诺多窗体,如果每个窗体都写一份,岂不太脑残?所以打算写一个基类,但是呢,Singleton只能被实例化一次,所以只好用了泛型来写。基类终于写好了,然后调试,发现确实可以控制窗体的打开个数,即被多次打开,但是呢,当窗体操作完成并关闭后,,再次打开这个窗体时就会出现(无法访问已释放的对象)的错误。 这里呢就有关系到C#中的垃圾回收问题。C#垃圾回收器管理所有的托管对象,所有需要托管数据的.NET语言(包括 C#)都受运行库的垃圾回收器的制约。垃圾回收器可以确定运行垃圾回收的最佳时间,自动进行垃圾回收。然而垃圾回收的一个产物是:C#对象没有确定性毁坏。所以会出现子窗口对象已被销毁,但又不为null,故出现访问时产生“未处理 ObjectDisposedException”异常(来自于“从小处看C#.net垃圾回收”一文)。
这里呢关于这个问题,因为不是主体所涉及,就不过多赘述,有兴趣的请大家自己查阅相关资料。回到正题,这又怎么办呢,有办法。问题的关键是,窗体已被释放,但因为还未来得及被系统处理,所以有Instance.Isdisposed=true,而Instance却不等null;怎么办呢,在窗体关闭的时候,可以人为地将其置为null;然后问题又出来了,Singleton为只读啊,如果你为Instance赋值,系统会报错,Instance为只读。怎么办呢,没办法,不撞南墙不回头,下定决心就做下去。要让它能被赋值,只能加上一个set了,这样再调试,一切就问题解决了。首先,窗体的重复或多次打开问题解决了;然后呢,每个窗体打开时,只要一行代码就搞定了,不用每个窗体写一份属性,方法(其实质还是借鉴Singleton);最后呢,不会出现再次打开不能访问的问题,即无法访问已释放的对象的问题。
以下是Singleton基类C#代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace dchtgl
{
//泛型实现实例单件化
public class Singleton<T> where T :new()
{
private static T instance = default(T);
private static readonly object lockHelper = new object();
private Singleton() { }
public static T Instance
{
get
{
if (instance == null)
{
lock (lockHelper)
{
if (instance == null)
{
instance = new T();
}
}
}
return instance;
}
set
{
instance = value;
}
}
}
}
如果要在主窗体中打开某个窗体,比如Form1,代码如下:
//Form1为MDI子窗体
private void 会员管理ToolStripMenuItem_Click(object sender, EventArgs e)
{
Form1 F1 = Singleton<Form1>.Instance;
F1.MdiParent = this;
F1.Show();
}
但要注意的是,必须在该窗体关闭时,加上
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
Singleton<Form1>.Instance = null;
}
这样才不会出问题。这回应该清楚了吧。
对于这个问题,最近有了新的认识,把代码贴出来以飨读者。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace dchtgl
{
/// <summary>
/// 泛型实现窗体实例单件化
/// </summary>
/// <typeparam name="T">窗体类</typeparam>
public static class Singleton<T> where T : Form, new()
{
private static T instance = default(T);
private static readonly object lockHelper = new object();
/// <summary>
/// 获取窗体的唯一实例
/// </summary>
public static T Instance
{
get
{
if (instance == null)
{
lock (lockHelper)
{
if (instance == null)
{
instance = new T();
//加上实例关闭事件,窗体就会自动回收,即instance=null;
instance.FormClosed += new FormClosedEventHandler(DestroyForm);
}
}
}
return instance;
}
}
/// <summary>
/// 当窗体关闭时将Instance置空
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void DestroyForm(object sender, FormClosedEventArgs e)
{
instance = default(T);
}
}
}
用法同上,但是不必在窗体关闭的时候,加上
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
Singleton<Form1>.Instance = null;
}
这一句了。
单件模式Singleton来控制窗体被重复或多次打开的更多相关文章
- 设计模式 - 单件模式(singleton pattern) 具体解释
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/u012515223/article/details/28595349 单件模式(singleton ...
- 设计模式(二)单件模式Singleton(创建型)
SINGLETON(单件)—对象创建型模式 几乎所有面向对象的程序中,总有一些类的对象需要是唯一的,例如,通过数据库句柄到数据库的连接是独占的.您希望在应用程序中共享数据库句柄,因为在保持连接打开或关 ...
- [MyBean-说明书]关于插件的单件模式(singleton),插件的共享模式
[说明] 单件模式是一种用于确保整个应用程序中只有一个类实例. 想想我们的系统中有哪些方面可以应用到单件模式,比如大家常说的连接(ADOConnection)共享,其实就是指的单件模式. [MyBea ...
- C#设计模式——单件模式(Singleton Pattern)
一.概述在软件开发过程中,我们有时候需要保证一个类仅有一个实例,比如在一个电脑用户下只能运行一个outlook实例.这时就需要用到单件模式.二.单件模式单件模式保证一个类仅有一个实例,并提供一个访问它 ...
- 说说设计模式~单件模式(Singleton)
单件模式(Singleton)要求一个类有且仅有一个实例,并且提供了一个全局的访问点. 从概念上来研究一下它的实现,不考虑线程安全 1 public sealed class Singlton 2 { ...
- 夜话JAVA设计模式之单例模式(单件模式Singleton)
单例模式也叫单件模式,就是确保一个类只有一个实例,并提供一个全局访问点. 设计成单例即把某个类设计成我们自己管理的单独实例,避免实例对象的重复创建,我们只有通过单例类的全局访问点获取实例. 下面来看金 ...
- 设计模式----创建型型模式之单件模式(Singleton pattern)
单件模式,又称单例模式,确保一个类只有一个实例,并提供全局访问点. 单件模式是比较简单且容易理解的一种设计模式.只有一个实例,通常的做法...TODO 类图比较简单,如下所示: 示例代码: 懒汉模式( ...
- 单件模式(Singleton)C++实现
意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点. 实用性:1.当类只能有一个实例而且客户可以从一个众所周知的访问点访问它. 2.当这个唯一的实例应该是通过子类可扩展的,并且客户应该无需更改 ...
- 1.单件模式(Singleton Pattern)
意图:为了保证一个类仅有一个实例,并提供一个访问它的全局访问点. 1.简单实现(多线程有可能产生多个实例) public class CommonSigleton { /// <summary& ...
随机推荐
- topcoder算法练习2
Problem Statement In most states, gamblers can choose from a wide variety of different lottery ...
- Linux ./configure && make && make install 编译安装和卸载
正常的编译安装/卸载: 源码的安装一般由3个步骤组成:配置(configure).编译(make).安装(make install). configure文件是一个可执行的脚本文件,它有很多选项, ...
- 简单实现tab标签页切换
常见面试题: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UT ...
- TatukGIS - GisDefs - CreateMSJET 函数
函数名称 CreateMSJET 所在单元 GisDefs 函数原型 function CreateMSJET(const _path: String): String; ...
- 简单工厂模式的C++实现
用简单工厂模式实现一个计算器类: #include <iostream> #include <string> using namespace std; class Operat ...
- iOS 的 XMPPFramework 简介一
XMPPFramework是一个OS X/iOS平台的开源项目,使用Objective-C实现了XMPP协议(RFC-3920),同时还提供了用于读写XML的工具,大大简化了基于XMPP的通信应用的开 ...
- sqlserver cte递归向上统计
数据字典如下
- iscc2016-basic-明察秋毫
查看源代码,找到maybe not flag : Jr1p0zr2VfPp 移位密码,注意判断字母大小写,并且数字无变化 s = "Jr1p0zr2VfPp" p = list(s ...
- Hybrid UI framework shootout: Ionic vs. Famo.us vs. F7 vs. OnsenUI
1 Introduction In the past 2 years I’ve been working intensively on mobile applications, mostly hybr ...
- 用expect实现自动输入SSH的SCP信息,且不需要另外的文件
#!/bin/sh ] ; then echo "USAGE: $0 remote_ip serverXXXXX" echo " e.g.: $0 1.2.3.4 ser ...