设计模式二-----单件模式
单件模式的主要用途在于控制某个类型的实例数量–有且仅有一个,例如与统计相关业务需求实现。(单件模式的主要意图就是控制该类只能够创建一个实例,同时向客户程序提供唯一访问它的全局访问点)
试图通过经典单件模式实现分布式环境下的“单件”不现实,因此,项目中的“单”字是有上下文和语义范围限制

一、实现单件的方式
外部方式:
客户程序使用某些全局对象时,做一些Try-Use的工作;
如果没有,就自己创建一个,把它放在全局位置上;
如果原本有,就直接用一个现成的。
内部方式:
类型自己控制生成实例的数量,无论客户程序是否Try过,类型自己控制就提供一个实例,客户程序使用的都是这个现成的唯一的实例
相比较而言,外部方式很不可靠,毕竟实例不只是一个,同时也不能做到全部的客户程序都做这种唯一性的检查。内部方式把干扰因素排除在类型之外,相对更保险一些
二、多线程问题
值得注意的问题是单件模式遇到多线程调用问题
1、可以添加关键字(volatilc,表示字段可能被多个线程修改,但是不接受编译器优化,也就是说在任何时间访问读是一个值)
2、在调用前提升变量范围的方式解决
3、实例构造函数私有化,公共静态成员访问
代码细节问题
1、不要实现ICloeable接口或者继承自其相关的子类,否则客户程序可以跳过已经隐藏的类构造函数
2、严防序列化,因为序列化事实上完成了Singleton对象的复制和重现
三、粗细粒度的单件模式
除了线程安全外,还需要注意单件模式的粗细粒度问题。例如某个线程是长时间运行的后台任务,他本身存在很多模块和中间块处理,但每个线程都希望有自己的线程内单独Singleton对象,其他线程也独立操作自己的线程内Singleton,这样Singleton的实例总数 = 1(每个线程内部唯一一个) * N (线程数) = N。
另外,需要注意桌面应用和Web应用中粗细粒度问题,实际问题需要适应的方法。
四、分布环境下的单件模式
除了限制在一个进程内,软件性能可以进一步提升,很多关键应用都需要到集群实现水平扩展。
之前在一个线程内部,为了实现一个线程安全的唯一实例就需要大费周章地做一个Double Check或取巧地采用》NET Framework内置机制。
当2个以上内部都保存一个具有new Singleton()能力的类型后,常规的单件模式很难控制他们的实现,这时直接剥夺他们new Singleton()的能力,双方之间增加一个代理,由这个代理向本进程内部的实体提供远程Singleton实例的引用,把构造工作从本地剥离到远程。
如果是Cluster环境,远程调用可能运行在集群的Controller节点上,也可以运行在某个Controller+Member的机器上;如果仅仅是一台机器的多个进程间通信,它可以“寄生”在某个进程独立内部,或者自己在一个单独的进程里。
另外,还有一个班Singleton的方式,内涵上单件模式要求的“唯一性”是为了内容的统一一致,既要确保所有关于某些内容的修改是同步的。因为如果内容自己是能“同步”的,那么是最好的。
五、单件模式的使用问题
经典单件模式实现上总是会在内存中保留一个一致驻留内存的实例,尽管这也是模式意图所在,但这往往不适合那些需要长时间持续运行的程序,因为变化总是存在,对它的任何修改都需要重启进程。
为了避免这个问题,可以根据需要为单件对象增加一个维护方法,允许外部程序或者工具调整单件对象成员;也可以设计一个Timer,赋予其自维护性。
同时,单件对象的存在多少也会程序的扩展性受到一定程度的限制。
六、小结
单件模式更多地强调构造数量的唯一性。
工程上实现Singleton的挑战主要来自于它的运行环境和需要保持Singleton特质的颗粒度,为了降低技术实施风险可以借助数据库、共享进程等方式近似解决分布式环境下Singleton的实现。
leton特质的颗粒度,为了降低技术实施风险可以借助数据库、共享进程等方式近似解决分布式环境下Singleton的实现。
本文详细介绍了设计模式中的单件模式,包括实现单件模式的内外部方式、多线程问题的处理、粗细粒度的考量以及分布环境下的应用。强调了单件模式在控制实例数量和保证一致性上的作用,并探讨了其在长时间运行程序和分布式环境中的挑战与解决方案。
2499

被折叠的 条评论
为什么被折叠?



