logo资料库

.net设计模式详细介绍以及案例代码.pdf

第1页 / 共60页
第2页 / 共60页
第3页 / 共60页
第4页 / 共60页
第5页 / 共60页
第6页 / 共60页
第7页 / 共60页
第8页 / 共60页
资料共60页,剩余部分请下载后查看
.NET 设计模式开篇 ——.NET 设计模式系列之一 Terrylee,2005 年 12 月 06 日 前言 加入 Design & Pattern 团队有几个月的时间了,惭愧的是从没有写过关于设计模式的随笔,得 到 wayfarer 的同意,把企业库系列的随笔放在了团队的首页上。不是不想去写这样的随笔,也 不是没有时间,自己初学设计模式,去写设计模式的文章,有点班门弄斧的味道。园子里吕震宇 老师的《设计模式系列》和 wayfarer 的《设计之道》堪称设计模式里的经典之作。可是正如 wa farer 所说的那样,受到发表欲的蛊惑,本着交流就是进步的想法,思考再三,还是决定写这样 的随笔,来对设计模式做一些探索和总结,起名曰“探索设计模式”,有些言过其实,就当是记 录自己学习设计模式的历程吧,不过还是希望能得到各位前辈的指点! 设计模式 设计模式是规则吗? 地上本没有路,走得人多了也就成了路。设计模式如同此理,它是经验的传承,并非体系;是被 前人发现,经过总结形成了一套某一类问题的一般性解决方案,而不是被设计出来的定性规则; 它不像算法那样可以照搬照用。 设计模式是架构吗? 架构和模式应该是一个属于相互涵盖的过程,但是总体来说架构更加关注的是所谓的 High-Leve l Design,而模式关注的重点在于通过经验提取的“准则或指导方案”在设计中的应用,因此在 不同层面考虑问题的时候就形成了不同问题域上的模式。模式的目标是,把共通问题中的不变部 分和变化部分分离出来。不变的部分,就构成了模式,因此,模式是一个经验提取的“准则”,
并且在一次一次的实践中得到验证,在不同的层次有不同的模式,小到语言实现,大到架构。在 不同的层面上,模式提供不同层面的指导。 设计模式,软件的永恒之道? 这个问题没有答案,有的只是讨论,看一下一位前辈结合建筑学得出的几点心得吧: 和建筑结构一样,软件中亦有诸多的“内力”。和建筑设计一样,软件设计也应该努力疏解系统中 的内力,使系统趋于稳定、有生气。一切的软件设计都应该由此出发。 任何系统都需要有变化,任何系统都会走向死亡。作为设计者,应该拥抱变化、利用变化,而不 是逃避变化。 好的软件只能“产生”而不能“创造”,我们所能做的只是用一个相对好的过程,尽量使软件朝向好 的方向发展。 需要设计模式吗? 答案是肯定的,但你需要确定的是模式的应用是否过度?我得承认,世界上有很多天才的程序员, 他可以在一段代码中包含 6 种设计模式,也可以不用模式而把设计做得很好。但我们的目标是 追求有效的设计,而设计模式可以为这个目标提供某种参考模型、设计方法。 我们不需要奉 GOF 的设计模式为圭臬,但合理的运用设计模式,才是正确的抉择。很多人看过 G OF 的《Design Patterns》,对这 23 种模式也背得滚瓜烂熟。但重要的不是你熟记了多少个模 式的名称,关键还在于付诸实践的运用。为了有效地设计,而去熟悉某种模式所花费的代价是值 得的,因为很快你会在设计中发现这种模式真的很好,很多时候它令得你的设计更加简单了。 其实在软件设计人员中,唾弃设计模式的可能很少,盲目夸大设计模式功用的反而更多。言必谈 “模式”,并不能使你成为优秀的架构师。真正出色的设计师,懂得判断运用模式的时机。还有
一个问题是,很多才踏入软件设计领域的人员,往往对设计模式很困惑。对于他们来说,由于没 有项目的实际经验,OO 的思想也还未曾建立,设计模式未免过于高深了。其实,即使是非常有 经验的程序员,也不敢夸口对各种模式都能合理应用。[--摘自 wayfare 的设计之道] 后记 关于设计模式的理论性的文章,已经写了很多了,我不想再继续重复抄写下去,仅记录下上面几 段话,用它来作探索设计模式系列的一个开篇吧。[现已更名为.NET 设计模式]
第Ⅱ部分 创建型模式篇 单件模式(Singleton Pattern) ——.NET 设计模式系列之二 Terrylee,2005 年 12 月 07 日 概述 Singleton 模式要求一个类有且仅有一个实例,并且提供了一个全局的访问点。这就提出了一个 问题:如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例?客户程序在调用某一 个类时,它是不会考虑这个类是否只能有一个实例等问题的,所以,这应该是类设计者的责任, 而不是类使用者的责任。 从另一个角度来说,Singleton 模式其实也是一种职责型模式。因为我们创建了一个对象,这个 对象扮演了独一无二的角色,在这个单独的对象实例中,它集中了它所属类的所有权力,同时它 也肩负了行使这种权力的职责! 意图 保证一个类仅有一个实例,并提供一个访问它的全局访问点。 模型图 逻辑模型图: 物理模型图: 生活中的例子 美国总统的职位是 Singleton,美国宪法规定了总统的选举,任期以及继任的顺序。这样,在任 何时刻只能由一个现任的总统。无论现任总统的身份为何,其头衔"美利坚合众国总统"是访问这 个职位的人的一个全局的访问点。
五种实现 1.简单实现 1 public sealed class Singleton 2 { 3 static Singleton instance=null; 4 5 Singleton() 6 { 7 } 8 9 public static Singleton Instance 10 { 11 get 12 { 13 if (instance==null) 14 { 15 instance = new Singleton(); 16 } 17 return instance; 18 } 19 } 20 } 这种方式的实现对于线程来说并不是安全的,因为在多线程的环境下有可能得到 Singleton 类的 多个实例。如果同时有两个线程去判断(instance == null),并且得到的结果为真,这时两个 线程都会创建类 Singleton 的实例,这样就违背了 Singleton 模式的原则。实际上在上述代码中, 有可能在计算出表达式的值之前,对象实例已经被创建,但是内存模型并不能保证对象实例在第 二个线程创建之前被发现。 该实现方式主要有两个优点: 由于实例是在 Instance 属性方法内部创建的,因此类可以使用附加功能 (例如,对子类进行实例化),即使它可能引入不想要的依赖性。 直到对象要求产生一个实例才执行实例化;这种方法称为“惰性实例化”。 惰性实例化避免了在应用程序启动时实例化不必要的 singleton。 2.安全的线程
1 public sealed class Singleton 2 { 3 static Singleton instance=null; 4 static readonly object padlock = new object(); 5 6 Singleton() 7 { 8 } 9 10 public static Singleton Instance 11 { 12 get 13 { 14 lock (padlock) 15 { 16 if (instance==null) 17 { 18 instance = new Singleton(); 19 } 20 return instance; 21 } 22 } 23 } 24 } 25 26 这种方式的实现对于线程来说是安全的。我们首先创建了一个进程辅助对象,线程在进入时先对 辅助对象加锁然后再检测对象是否被创建,这样可以确保只有一个实例被创建,因为在同一个时 刻加了锁的那部分程序只有一个线程可以进入。这种情况下,对象实例由最先进入的那个线程创 建,后来的线程在进入时(instence == null)为假,不会再去创建对象实例了。但是这种实现 方式增加了额外的开销,损失了性能。 3.双重锁定 1 public sealed class Singleton 2 { 3 static Singleton instance=null; 4 static readonly object padlock = new object(); 5 6 Singleton() 7 { 8 } 9 10 public static Singleton Instance 11 {
12 get 13 { 14 if (instance==null) 15 { 16 lock (padlock) 17 { 18 if (instance==null) 19 { 20 instance = new Singleton(); 21 } 22 } 23 } 24 return instance; 25 } 26 } 27 } 28 这种实现方式对多线程来说是安全的,同时线程不是每次都加锁,只有判断对象实例没有被创建 时它才加锁,有了我们上面第一部分的里面的分析,我们知道,加锁后还得再进行对象是否已被 创建的判断。它解决了线程并发问题,同时避免在每个 Instance 属性方法的调用中都出现独 占锁定。它还允许您将实例化延迟到第一次访问对象时发生。实际上,应用程序很少需要这种类 型的实现。大多数情况下我们会用静态初始化。这种方式仍然有很多缺点:无法实现延迟初始化。 4.静态初始化 1 public sealed class Singleton 2 { 3 static readonly Singleton instance=new Singleton(); 4 5 static Singleton() 6 { 7 } 8 9 Singleton() 10 { 11 } 12 13 public static Singleton Instance 14 { 15 get 16 { 17 return instance; 18 } 19 } 20 } 21
看到上面这段富有戏剧性的代码,我们可能会产生怀疑,这还是 Singleton 模式吗?在此实现中, 将在第一次引用类的任何成员时创建实例。公共语言运行库负责处理变量初始化。该类标记为 sealed 以阻止发生派生,而派生可能会增加实例。此外,变量标记为 readonly,这意味着只 能在静态初始化期间(此处显示的示例)或在类构造函数中分配变量。 该实现与前面的示例类似,不同之处在于它依赖公共语言运行库来初始化变量。它仍然可以用来 解决 Singleton 模式试图解决的两个基本问题:全局访问和实例化控制。公共静态属性为访问 实例提供了一个全局访问点。此外,由于构造函数是私有的,因此不能在类本身以外实例化 Singleton 类;因此,变量引用的是可以在系统中存在的唯一的实例。 由于 Singleton 实例被私有静态成员变量引用,因此在类首次被对 Instance 属性的调用所引 用之前,不会发生实例化。 这种方法唯一的潜在缺点是,您对实例化机制的控制权较少。在 Design Patterns 形式中,您 能够在实例化之前使用非默认的构造函数或执行其他任务。由于在此解决方案中由 .NET Framework 负责执行初始化,因此您没有这些选项。在大多数情况下,静态初始化是在 .NET 中 实现 Singleton 的首选方法。 5.延迟初始化 1 public sealed class Singleton 2 { 3 Singleton() 4 { 5 } 6 7 public static Singleton Instance 8 { 9 get 10 { 11 return Nested.instance; 12 } 13 } 14 15 class Nested 16 { 17 static Nested() 18 { 19 } 20 21 internal static readonly Singleton instance = new Singleto n(); 22 } 23 } 24 这里,初始化工作有 Nested 类的一个静态成员来完成,这样就实现了延迟初始化,并具有很多 的优势,是值得推荐的一种实
分享到:
收藏