热门标签 | 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



推荐阅读
  • 在基于.NET框架的分层架构实践中,为了实现各层之间的松散耦合,本文详细探讨了依赖注入(DI)和控制反转(IoC)容器的设计与实现。通过合理的依赖管理和对象创建,确保了各层之间的单向调用关系,从而提高了系统的可维护性和扩展性。此外,文章还介绍了几种常见的IoC容器实现方式及其应用场景,为开发者提供了实用的参考。 ... [详细]
  • 如何使用 net.sf.extjwnl.data.Word 类及其代码示例详解 ... [详细]
  • 本文将详细介绍在Android应用中添加自定义返回按钮的方法,帮助开发者更好地理解和实现这一功能。通过具体的代码示例和步骤说明,本文旨在为初学者提供清晰的指导,确保他们在开发过程中能够顺利集成返回按钮,提升用户体验。 ... [详细]
  • 本章节在上一章的基础上,深入探讨了如何通过引入机器人实现自动聊天、表情包回应以及Adidas官方账号的自动抽签功能。具体介绍了使用wxpy库进行微信机器人的开发,优化了智能回复系统的性能和用户体验。通过详细的代码示例和实践操作,展示了如何实现这些高级功能,进一步提升了机器人的智能化水平。 ... [详细]
  • 本文深入探讨了CGLIB BeanCopier在Bean对象复制中的应用及其优化技巧。相较于Spring的BeanUtils和Apache的BeanUtils,CGLIB BeanCopier在性能上具有显著优势。通过详细分析其内部机制和使用场景,本文提供了多种优化方法,帮助开发者在实际项目中更高效地利用这一工具。此外,文章还讨论了CGLIB BeanCopier在复杂对象结构和大规模数据处理中的表现,为读者提供了实用的参考和建议。 ... [详细]
  • 深入解析JWT的实现与应用
    本文深入探讨了JSON Web Token (JWT) 的实现机制及其应用场景。JWT 是一种基于 RFC 7519 标准的开放性认证协议,用于在各方之间安全地传输信息。文章详细分析了 JWT 的结构、生成和验证过程,并讨论了其在现代 Web 应用中的实际应用案例,为开发者提供了全面的理解和实践指导。 ... [详细]
  • 本课程详细介绍了如何使用Python Flask框架从零开始构建鱼书应用,涵盖高级编程技巧和实战项目。通过视频教学,学员将学习到Flask的高效用法,包括数据库事务处理和书籍交易模型的实现。特别感谢AI资源网提供的课程下载支持。 ... [详细]
  • 在MFC框架中,存在多个全局函数,用于在不同对象间获取信息或创建新对象。其中,`afxGetApp`函数尤为关键,它能够帮助开发者轻松获取当前应用程序的实例指针。本文将详细解析`afxGetApp`函数的内部机制及其在MFC应用程序中的具体应用场景,探讨其在提升代码可维护性和灵活性方面的优势。此外,还将介绍其他常用全局函数如`AfxWinInit()`和`AfxBeginThread()`的功能和使用方法,为开发者提供全面的参考。 ... [详细]
  • 在《PHP应用性能优化实战指南:从理论到实践的全面解析》一文中,作者分享了一次实际的PHP应用优化经验。文章回顾了先前进行的一次优化项目,指出即使系统运行时间较长后出现的各种问题和性能瓶颈,通过采用一些通用的优化策略仍然能够有效解决。文中不仅详细阐述了优化的具体步骤和方法,还结合实例分析了优化前后的性能对比,为读者提供了宝贵的参考和借鉴。 ... [详细]
  • MySQL 错误:检测到死锁,在尝试获取锁时;建议重启事务(Node.js 环境)
    在 Node.js 环境中,MySQL 数据库操作时遇到了“检测到死锁,在尝试获取锁时;建议重启事务”的错误。本文将探讨该错误的原因,并提供有效的解决策略,包括事务管理优化和锁机制的理解。 ... [详细]
  • 在Spring与Ibatis集成的环境中,通过Spring AOP配置事务管理至服务层。当在一个服务方法中引入自定义多线程时,发现事务管理功能失效。若不使用多线程,事务管理则能正常工作。本文深入分析了这一现象背后的潜在风险,并探讨了可能的解决方案,以确保事务一致性和线程安全。 ... [详细]
  • 全面解析Java虚拟机:内存模型深度剖析 ... [详细]
  • Java 零基础入门:SQL Server 学习笔记(第21篇)
    Java 零基础入门:SQL Server 学习笔记(第21篇) ... [详细]
  • 在处理大规模并发请求时,传统的多线程或多进程模型往往无法有效解决性能瓶颈问题。尽管它们在处理小规模任务时能提升效率,但在高并发场景下,系统资源的过度消耗和上下文切换的开销会显著降低整体性能。相比之下,Python 的 `asyncio` 模块通过协程提供了一种轻量级且高效的并发解决方案。本文将深入解析 `asyncio` 模块的原理及其在实际应用中的优化技巧,帮助开发者更好地利用协程技术提升程序性能。 ... [详细]
  • MySQL 数据操作:增、删、查、改全面解析
    MySQL 数据操作:增、删、查、改全面解析 ... [详细]
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社区 版权所有