1.缘起:
假设我们的订单处理系统所要处理的订单是有优先级的,也就是说,不同的订单类型所要求被处理的紧迫程度不同,对那些优先级高的注单要先处理,对于优先级低的注单可稍后处理。对于处于同一优先级的订单了,就按照其到达的先后顺序进行处理。
这是一个典型的管理具有优先级的对象的需求,注单就是具有优先级(With Priority)的对象。我设计了ESBasic.ObjectManagement.Managers.IPriorityManager优先级管理器(确切地说,应该称之为“具有优先级对象的管理器”)来对类似的对象进行管理。
优先级管理器的形象示意图如下:
2.适用场合:
如果你的系统需要对被管理的对象进行优先级分级,并满足以下条件,则可使用IPriorityManager:
(1)对象需要按优先级别(PriorityLevel)进行分类。
(2)优先级别的划分是固定的,不会随系统的运行而发生变化。
(3)对处于同一优先级别的对象,采用先来后到的顺序进行“第二优先级”的高低确定。
(4)优先级别可以使用>=0的连续整数来表示。
3.设计思想与实现
在前面的叙述中,具有优先级对象的管理器的功能职责是相当清晰明了的,在进入其实现之前,首先我们要解决的一个问题是,如何对处于同一优先级别的对象进行管理。根据前面的需求描述,如果两个对象处于相同的优先级别,则先到达的对象的优先程度(即所谓的“第二优先级”)更高。
我使用ESBasic.ObjectManagement.Managers.ISamePriorityObjectManager(同一优先级别对象管理器)来管理属于同一优先级别的所有对象,其接口定义如下:
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> publicinterfaceISamePriorityObjectManager<T>
{
///<summary>
///AddWaiter添加一个等待者。如果等待者在管理器中已经存在,则直接返回。
///</summary>
voidAddWaiter(Twaiter);
///<summary>
///Count当前管理器中等待者的数量。
///</summary>
intCount{get;}
///<summary>
///GetNextWaiter返回等待时间最长的waiter。
///注意,返回时并不会从等待列表中删除waiter。如果要删除某个等待者,请调用RemoveWaiter。
///</summary>
TGetNextWaiter();
///<summary>
///GetWaitersByPriority按照等待者加入的先后顺序返回等待者数组,数组中index越小的等待者其等待时间越长,其优先级也越高。
///</summary>
T[]GetWaitersByPriority();
///<summary>
///RemoveWaiter从管理器中移除指定的等待者。
///</summary>
voidRemoveWaiter(Twaiter);
///<summary>
///Clear清空管理器中的所有等待者。
///</summary>
voidClear();
///<summary>
///Contains管理器中是否存在指定的等待者。
///</summary>
boolContains(Twaiter);
}
在ISamePriorityObjectManager所表述的语义环境中,被管理的对象称为“等待者”waiter――这表示一个对象等待被处理。
关于SamePriorityObjectManager的实现,有以下几点需要说明:
(1)其内部是使用LinkedList而不是Queue来存储等待者的,其主要原因在于SamePriorityObjectManager需要支持移除管理器中任一等待者的RemoveWaiter方法。由于Queue本身不支持任意位置的删除功能,所以我使用了LinkedList。新加入的等待者将被放在LinkedList的最后位置。
(2)当管理器中没有任何等待者时,GetNextWaiter方法将返回default(T),如果T是值类型,则此时GetNextWaiter返回的可能并不是一个你所期望的对象。所以,如果T是值类型,在调用GetNextWaiter之前先访问一下其Count属性确保管理器中还有等待者存在。
(3)SamePriorityObjectManager使用了前面介绍的SmartRWLocker来对内部的waiterList进行读写锁控制。
在讨论完SamePriorityObjectManager的实现以后,我们将注意力转移到本节的主角IPriorityManager上来,IPriorityManager的接口定义如下:
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> ///<summary>
///IPriorityManager具有优先级的对象的管理器。
///</summary>
///<typeparamname="T">被管理的对象的类型,必须从IPriorityObject继承。</typeparam>
publicinterfaceIPriorityManager<T>:ISamePriorityObjectManager<T>whereT:class,IPriorityObject
{
intPriorityLevelCount{get;set;}
}
IPriorityManager接口直接从ISamePriorityObjectManager继承,并没有多加任何方法,唯一增加的就是一个PriorityLevelCount属性和要求被管理的对象的类型必须是从IPriorityObject接口继承的一个泛型约束。
PriorityLevelCount用于设定你的系统需要有几种优先级别。比如,我的订单基于紧急的优先级可分为紧急、普通、不紧急三种,那么就可将PriorityLevelCount属性设置为3。
一个类型从IPriorityObject接口继承,就表明它的实例是具有优先级属性的对象。
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->///<summary>
///IPriorityObject具有优先级的对象的接口。
///</summary>
publicinterfaceIPriorityObject
{
intPriorityLevel{get;}
}
为什么ISamePriorityObjectManager没有要求被管理的对象继承自IPriorityObject接口了?这是因为在ISamePriorityObjectManager的职责中,其仅仅是根据对象的先后顺序来确定“第二优先级”的,这并不是真正意义上的优先级别,所以没有必要为其单独抽象出一个IPriorityObject接口来。同时,ISamePriorityObjectManager不要求被管理的对象继承自IPriorityObject接口也是为了扩大其被单独复用的范围。
IPriorityManager接口直接从ISamePriorityObjectManager接口继承,说明IPriorityManager实际上要做工作与ISamePriorityObjectManager是相同的,只不过IPriorityManager管理的对象需要首先按优先级别进行分类,然后再使用ISamePriorityObjectManager管理处于同一优先级别的对象。
接下来我们看PriorityManager的具体实现。
在PriorityManager中,有这样的一个约定:优先级别是用int表示的,其值是从0开始连续的一串整数,整数值越小,表明优先级越高。当Initialize方法被执行后,优先等级的范围就被固定下来。比如PriorityLevelCount值设为4,则PriorityManager所支持的优先等级即为:0,1,2,3。
基于这样的约定,PriorityManager内部使用了一个ISamePriorityObjectManager数组,数组的索引值就对应着优先级别值。比如,数组中index为1的ISamePriorityObjectManager管理器中的所有对象的优先级别值都是1。
有了这两点认识,再看PriorityManager的源码就相当容易了,下面是其中的关键点:
(1)在类似AddWaiter、RemoveWaiter这样的方法实现中,都是先通过其参数对象的PriorityLevel属性定位到对应的ISamePriorityObjectManager管理器,然后再做进一步的处理的。
(2)如果目标对象的PriorityLevel属性值超过了约定的范围,PriorityManager会根据当前的情况做灵活的处理。比如,如果是调用AddWaiter加入一个这样的对象,则会抛出一个“不支持该优先级别”的异常;而如果是在类似RemoveWaiter这样的方法中,则会忽略这个对象。
(3)如果PriorityManager管理器中没有任何对象时,PriorityManager的GetNextWaiter方法直接返回null,而不是default(T),这是因为在PriorityManager定义的泛型约束中,要求T必须是一个引用类型。这就没有了前面提到的SamePriorityObjectManager的GetNextWaiter方法的返回值可能导致的问题。
(4)GetWaitersByPriority方法返回的对象数组具有这样的特征:优先级别越高的对象,其在数组中的位置索引就越小;同一优先级别的对象,加入时间越早的,其在数组中的位置索引越小。
4. 使用时的注意事项
(1) 如果你的系统仅仅需要按照对象的到达顺序来决定先后处理的顺序,那么直接使用ISamePriorityObjectManager就可以满足需求了,没有必要使用IPriorityManager这个更复杂的类。使用ISamePriorityObjectManager还有一个好处就是,被管理的对象不需要实现IPriorityObject接口,这样使用起来会更加方便。
(2) 如果在你的系统中不是使用0,1,2,3…这样的数值来表示优先级别的,那么你可以建立一个转换映射来完成优先级别值到数字的转换。并遵从PriorityManager所要求的约定。
(3) PriorityManager的Initialize方法一旦被调用后,其PriorityLevelCount属性便不应该被修改。或者说,即使该属性在之后被修改,也不会产生任何效果。
5.扩展
优先级管理器PriorityManager暂时没有任何扩展。
注:ESBasic源码可到http://esbasic.codeplex.com/下载。
ESBasic讨论:37677395
ESBasic开源前言
分享到:
相关推荐
本人将 zhuweisky博主的博客整理成了PDF文件,以便于脱机浏览,没有经过博主的同意就这么做 实在是不好意思^-^ 现将其资料免费下载 以示对博主的尊重 源博客地址:...
.NET设计规范:约定、惯用法与模式,在.net环境下进行开发设计的经典之作,权威指导.
LiteGo:「迷你」的Android异步并发类库LiteGo是一款基于Java语言的「异步并发类库」,它的核心是一枚「迷你」并发器,它可以自由地设置同一时段的最大「并发」数量,等待「排队」线程数量,还可以设置「排队策略」...
新版根据.NET Framework 3.0和3.5的新特性做了全面更新,主要关注的是直接影响框架可编程能力的设计问题。遵守这些规范对于使用.NET Framework创建高质量的应用程序至关重要。 本书提供配套光盘,内含Designing ...
NET应用架构设计原则、模式与实践.pdf NET应用架构设计原则、模式与实践.pdf
灵活易用的工作流组件、数据字典管理组件、在线表单设计组件、丰富的报表统计组件、即时通讯(IM)组件、邮件中心组件、微信开发相关组件、任务调度组件、自动升级组件、多语言模块,各种常用的商业控件,强大的代码...
新版根据.NET Framework 3.0和3.5的新特性做了全面更新,主要关注的是直接影响框架可编程能力的设计问题。遵守这些规范对于使用.NET Framework创建高质量的应用程序至关重要。 本书提供配套光盘,内含Designing ...
博文地址:http://blog.csdn.net/csnd_ayo/article/details/72457190
5.7.4 参数数量可变的成员 147 5.7.5 指针参数 150 5.8 小结 152 第6章 为扩展性而设计 153 6.1 扩展机制 153 6.1.1 非密封类 153 6.1.2 保护成员 155 6.1.3 事件与回调函数 156 6.1.4 虚成员 ...
自己写的ado.net类库,已实现有关数据库操作的各种方法,子类只需提供数据库连接,即可调用,极大了实现了代码复用.这是我针对实际开发中经常需要重复开发数据库操作而提出的解决方案. 注意,该类实现的是关于sqlserver...
这里收集一些著名的 C/C++ 开发库、SDK、类库、可复用类与结构代码 等信息,列举它们的介绍、参考和网站链接,为各位 C/C++ 程序员和爱好者提供检索和查阅类库的方便。 下面收集的 C/C++ 类库介绍整理来源于文章:...
逻辑与计算机设计基础,课后答案,很全很详细,每章节的答案都全面
有志于做JAVA系统性的技术提升的同学可与我联系,交个朋友哦~ 本人十余年JAVA架构设计经验,擅长JAVA高可用、分布式、高并发系统架构设计。有志于做JAVA系统性的技术提升的同学可与我联系,交个朋友哦~ 本人十余年...
Vue应用中抽离组件的目的是功能的解耦和复用 组件是通过处理组件配置对象生成的 组件配置对象的data选项是对象时:每个实例化生成的组件,它们的data都是组件配置对象中data对象的引用。也就是说每个组件都使用同一...
有志于做JAVA系统性的技术提升的同学可与我联系,交个朋友哦~ 本人十余年JAVA架构设计经验,擅长JAVA高可用、分布式、高并发系统架构设计。有志于做JAVA系统性的技术提升的同学可与我联系,交个朋友哦~ 本人十余年...
自从.NET推出以来,他已使用.NET帮助很多行业的用户开发了体现其商业理念的软件产品.Xin Chen是.NET和EAI方面的专家,他与Microsoft和Accenture等多家技术领先的公司合作,为它们的客户提供了优秀的解决方案....
此外,还可以创建一个新类库实现软件复用。 • 第十章介绍.NET下的数据库支持,阐述了ADO.NET的基本概念和结构,并通过示例詊细介绍C#下Web Service数据库访问的方法。 • 第十一章将在以前的基础上介绍一个...
这些规范历经.NET框架三个版本的长期开发,凝聚了数千名开发人员的经验和智慧。微软的各开发组正在使用这些规范开发下一代影响世界的软件产品。 第1章 概述 1 1.1 精心设计的框架所具备的品质 2 1.1.1 精心...
Android应用源码开发Demo,主要用于毕业设计学习。