热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

通俗道破单例模式

很多时候我们不知不觉中使用着设计模式,自己很多却不知道自己使用了,例如我们在涉及抽象类,接口的时候经常用到装饰者模式,在Wi

    很多时候我们不知不觉中使用着设计模式,自己很多却不知道自己使用了,例如我们在涉及抽象类,接口的时候经常用到装饰者模式,在Winfrom的窗体(当然还是类)复用中经常用到模板方法模式......反正什么是设计模式,学好多态是很重要的,言归正传。

    通常一个类通常可以创建无限个对象,但是有时候需要只有一个对象的类,比如全局资源管理器、缓存管理器等,这种情况下如果有多个对象就会乱掉了。缓存管理器只能有一个,否则把数据扔给一个管理器,却管另外一个要。

    就好比有一个老婆类,他的一个对象对我很好,但是不是随便那个老婆等可以对我好,应该只有我老婆对我好,因此我们要确定这个唯一的老婆。

    单例模式的意思就是只有一个实例。单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。

现在我们来看一个不是单例模式却有点类似的味道的小代码(至于为什么我稍后解释):

(读取文件内容:)未优化前的代码:

1 static void Main(string[] args)
2 {
3 Stopwatch sw=new Stopwatch();
4 sw.Start();
5 for (int i &#61; 0; i <100000; i&#43;&#43;)
6 {
7 string s&#61;File.ReadAllText(&#64;"d:\1.txt");
8 Console.WriteLine(s);
9 }
10 sw.Stop();
11 Console.WriteLine("耗时&#xff1a;"&#43;sw.Elapsed);
12 Console.ReadKey();
13 }

优化以后&#xff1a;

1 static void Main(string[] args)
2 {
3 Stopwatch sw&#61;new Stopwatch();
4 sw.Start();
5 string s &#61; null;
6 for (int i &#61; 0; i <100000; i&#43;&#43;)
7 {
8 if(s&#61;&#61;null)
9 {
10 s &#61; File.ReadAllText(&#64;"d:\1.txt");
11 }
12 Console.WriteLine(s);
13 }
14 sw.Stop();
15 Console.WriteLine("耗时&#xff1a;"&#43;sw.Elapsed);
16 Console.ReadKey();
17 }

    我先解释为什么不是单例模式&#xff0c;我们应该知道string 是CLR中String类的别名&#xff0c;也就是说我可以在这个小程序中创建很多的String类的对象&#xff0c;而且可以是不同的&#xff08;string a&#61;"";string b&#61;"123"......&#xff09;&#xff0c;所以没有实现确保某一个类只有一个实例的要求。

    我们来看一下优化前后代码执行的不同点&#xff0c;是第二段代码在每次循环的时候先查看下s是不是为空&#xff0c;如果不为空直接打印出s&#xff0c;不需要再次读文件&#xff08;当然此处的判断也是耗时间的哦&#xff0c;好像昨天一个网友还刚发表了什么关于不能从时间的长度看效率&#xff0c;反正我没看&#xff0c;不过这里咱们知道有优化效果就行了&#xff0c;要是真想提高效率必须研究数据结构和算法&#xff09;此处的s起了一个缓存的作用&#xff0c;使执行时间大大缩短。

单例模式的应用&#xff1a;

    有时候我们会遇到这种需求&#xff0c;就是频繁的从服务器下载资料进行对比&#xff0c;或者频繁的操作文件&#xff0c;我想了下vss的工作机制应该也是这个道理&#xff0c;如果我们的开发团队没有修改代码&#xff0c;调用的时候还是会返回缓存中的代码给某个程序员。

    譬如每台计算机可以有若干个打印机&#xff0c;但只能有一个Printer Spooler&#xff0c; 以避免两个打印作业同时输出到打印机中。每台计算机可以有若干传真卡&#xff0c;但是只应该有一个软件负责管理传真卡&#xff0c;以避免出现两份传真作业同时传到传真卡中的情况。每台计算机可以有若干通信端口&#xff0c;系统应当集中管理这些通信端口&#xff0c;以避免一个通信端口同时被两个请求同时调用。

    等等情况... ...

怎么实现单例模式

  实现单例模式的方法很多&#xff0c;常用的就像百度百科里面提到的&#xff1a;

第一种形式: 也是常用的形式。

1 public class Singleton
2 {
3 private static Singleton instance &#61; null;
4 private Singleton()
5 {   //do something  
6 }
7 public static Singleton getInstance()
8 {
9 if (instance &#61;&#61; null)
10 { instance &#61; new Singleton(); }
11 return instance;
12 }
13 } //这个方法比下面的有所改进&#xff0c;不用每次都进行生成对象&#xff0c;只是第一次使用时生成实例&#xff0c;提高了效率  

但是上面这个百度百科没有说明&#xff0c;就是如果是多线程并行操作可能会引起实例的冲突。

所以最好这样啦&#xff1a;

public static Singleton getInstance()
   {
                    return instance;
    }

 第二种形式:

1 public class Singleton
2 {   //在自己内部定义自己的一个实例&#xff0c;只供内部调用  
3 private static Singleton instance &#61; new Singleton();
4 private Singleton()
5 {
6 //do something  
7 }
8 //这里提供了一个供外部访问本class的静态方法&#xff0c;可以直接访问   
9 public static Singleton getInstance()
10 {
11 return instance;
12 }
13 }

 

现在我们模拟频繁读取同一个文件的内容&#xff08;使用单例模式&#xff09;&#xff1a;

1 using System;
2 using System.IO;
3 using System.Diagnostics;
4 using System.Collections.Generic;
5
6 namespace 单例模式
7 {
8 class Program
9 {
10 static void Main(string[] args)
11 {
12 Stopwatch sw &#61; new Stopwatch();
13 sw.Start();
14 for (int i &#61; 0; i <10000; i&#43;&#43;)
15 {
16 //因为Instance是唯一的实例
17 string s&#61; FileCache.instance.ReadFile(&#64;"d:\1.txt");
18 Console.WriteLine(s);
19 }
20 sw.Stop();
21 Console.WriteLine(sw.Elapsed);
22 Console.ReadKey();
23 }
24 }
25 class FileCache
26 {
27 public static readonly FileCache instance &#61; new FileCache();
28 private FileCache()
29 {
30 }
31 //创建一个字典用来保存文件信息&#xff0c;key是文件名&#xff0c;value是文件内容
32 private Dictionary<string, string> dic &#61; new Dictionary<string, string>();
33 public string ReadFile(string path)
34 {
35 if (dic.ContainsKey(path))
36 {
37 return dic[path];
38 }
39 string content &#61; File.ReadAllText(path);
40 dic.Add(path, content);
41 return content;
42 }
43 }
44 }

上面的代码我的硬件配置是i52430,2G CUP 运行了不到一秒。这段代码确保了我们每次操作的都是同一个实例。但是还有个问题就是我们我们及时在程序执行期间修改了文本文件里的内容&#xff0c;显示的仍然没有更新&#xff0c;怎么动态的修改文件并更新显示呢&#xff0c;这里我们就要新建一个内容管理类&#xff0c;保存上次更新的时间和现在内容&#xff0c;就可以了

1 using System;
2 using System.IO;
3 using System.Diagnostics;
4 using System.Collections.Generic;
5 using System.Threading;
6
7 namespace 单例模式
8 {
9 class Program
10 {
11 static void Main(string[] args)
12 {
13 Stopwatch sw &#61; new Stopwatch();
14 sw.Start();
15 for (int i &#61; 0; i <100000000; i&#43;&#43;)
16 {
17 //因为Instance是唯一的实例
18 string s&#61; FileCache.instance.ReadFile(&#64;"d:\1.txt");
19 Thread.Sleep(500);
20 Console.WriteLine(s);
21 }
22 sw.Stop();
23 Console.WriteLine(sw.Elapsed);
24 Console.ReadKey();
25 }
26 }
27 class FileCache
28 {
29 public static readonly FileCache instance &#61; new FileCache();
30 private FileCache()
31 {
32 }
33 private Dictionary<string, FileContentManager> dic &#61; new Dictionary<string, FileContentManager>();
34 public string ReadFile(string path)
35 {
36 if (dic.ContainsKey(path))
37 {
38 DateTime lastwritetime &#61; File.GetLastWriteTime(path);//获取上次写入文件的时间
39 if (lastwritetime &#61;&#61; dic[path].LastWriteTime)
40 {
41 return dic[path].Content;
42 }
43 }
44 string content &#61; File.ReadAllText(path);
45 FileContentManager txtmanger &#61; new FileContentManager();
46 ///&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;将信息保存到文件管理类中&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;
47 txtmanger.Content &#61; content;
48 txtmanger.LastWriteTime &#61; File.GetLastWriteTime(path);
49 ///&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;将信息保存到文件管理类中&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;
50 return content;
51 }
52 }
53 class FileContentManager
54 {
55 public string Content { get;set;}//内容
56 public DateTime LastWriteTime { get; set; }//修改时间
57 }
58 }

运行效果如下&#xff1a;

转:https://www.cnblogs.com/rohelm/archive/2012/04/29/2476107.html



推荐阅读
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • C# 7.0 新特性:基于Tuple的“多”返回值方法
    本文介绍了C# 7.0中基于Tuple的“多”返回值方法的使用。通过对C# 6.0及更早版本的做法进行回顾,提出了问题:如何使一个方法可返回多个返回值。然后详细介绍了C# 7.0中使用Tuple的写法,并给出了示例代码。最后,总结了该新特性的优点。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 本文介绍了深入浅出Linux设备驱动编程的重要性,以及两种加载和删除Linux内核模块的方法。通过一个内核模块的例子,展示了模块的编译和加载过程,并讨论了模块对内核大小的控制。深入理解Linux设备驱动编程对于开发者来说非常重要。 ... [详细]
  • 本文介绍了在wepy中运用小顺序页面受权的计划,包含了用户点击作废后的从新受权计划。 ... [详细]
author-avatar
七仙女跳皮筋
这个家伙很笨,什么也不会!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有