zhuweisky

君子之行,静以修身,俭以养德。非淡泊无以明志,非宁静无以致远。

ESFramework,基于.NET的通信框架。DataRabbit,轻量的数据访问框架。sky.zhuwei@163.com
posts - 191, comments - 1276, trackbacks - 94, articles - 1
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理

使用Null Object设计模式

Posted on 2007-02-28 19:34 zhuweisky 阅读(3292) 评论(15)  编辑 收藏 所属分类: C#专栏

   在ESFramework的设计实现中,很多地方都用到了Null Object设计模式。Null Object模式的含义在于,提供一个对象给指定的类型,用以代替这个对象为空的情况。 Null Object提供了“什么也不做”的行为,隐藏来自它的合作者的细节。
   对于如何理解和应用该模式,通过一个实例就能很好的进行说明。这一节我们在讨论消息分派器,消息分派器使用了前述的日志记录器,并且通过属性来注入具体的日志记录器对象。

        private IEsfLogger esfLogger;
        
public IEsfLogger EsfLogger
        {
            
set
            {
                
this.esfLogger = value;
            }
        }    

    现在假设,我们在消息分派器内部的多个地方使用日志记录器来进行日志记录,我们总要写这样的语句:

     if (this.esfLogger != null)
     {
          
this.esfLogger.Log(); //记录日志
     }

    也就是说,在使用之前,我们都要判断一下日志记录器的引用是否为空,如果不为空才可以调用其Log方法。如果调用日志记录器进行日志记录的地方很多,那么每个地方都会充斥着这种判断其引用是否为空的代码。有没有办法来避免这所有的判断语句了,有!那就是使用Null Object设计模式。
    ESFramework为每种必要的组件都提供了对应的Null Object类型,这些类型的名字以“Empty”作为前缀。比如IEsfLogger对应的Null Object类型就是EmptyEsfLogger,EmptyEsfLogger实现的Log方法什么也不用做:

        public void Log(string errorType ,string msg, string location, ErrorLevel level)
        {
            
//Do Nothing !
        }

   有了EmptyEsfLogger,我们就可以象这样来设计消息分派器的日志记录器属性:

        private IEsfLogger esfLogger = new EmptyEsfLogger();
        
public IEsfLogger EsfLogger
        {
            
set
            {
                
if (value != null)
                {
                    
this.esfLogger = value ?? new EmptyEsfLogger();
                }
            }
        }

   首先,将esfLogger字段的默认值设为一个Null Object。其次,当调用者每次试图将EsfLogger属性设置为null时,也将一个Null Object赋值给该字段。
   如此一来,在消息分配器内部,我们就可以非常方便的直接使用日志记录器,而不用再判断其引用是否为空,因为无论如何,它总是指向一个有效的对象,即使这个对象是Null Object。

    除了常见的组件装配可以使用Null Object模式外,还有一个非常适合使用Null Object模式的场合,那就是“事件”。你是否还记得,我们每次触发事件时都需要判断其是否为空,这也是非常琐碎的事情,我们仍然可以通过Null Object模式来简化它。比如某个类中定义了一个事件:

public event CbSimple SomeOneConnected;

在类的构造函数中,可以使用Null Object来初始化它:

this.SomeOneConnected += delegate { };

这样,在每次触发事件时就不用再判断其是否为null了:

this.SomeOneConnected(); //不用再判断是否为null,直接触发事件

   灵活地使用Null Object设计模式,可以使得我们的代码更加简洁和精炼。


注:本文节选自我的书稿 《.NET通信框架的设计、实现与应用》





Feedback

#1楼    回复  引用  查看    

2007-02-28 19:47 by JesseZhao      
呵呵,有了一些新的认识了

#2楼    回复  引用  查看    

2007-02-28 20:04 by reonlyrun      
似懂非懂

#3楼    回复  引用  查看    

2007-02-28 20:47 by 代码乱了      
不是太懂哦
支持

#4楼    回复  引用    

2007-02-28 21:55 by 怀宁梧桐 [未注册用户]
敬请网上搜索“怀宁梧桐”四字,来本人法律博客过目、指正以下文章(现时的“和讯网怀宁梧桐”博文后方便您发表评论,本人亦可回复)——

《再问头号大腐》
《公开批评中央高层领导人》

《让贪官胆寒的怀宁梧桐同志何在?!》

《拉开反腐大幕——怀宁梧桐心语告同志和亿万人民》
《入“人穴” 探“正”路》

和***《沁园春·雪》——《沁园春·治》
和***《念奴娇·鸟儿问答》——《念奴娇·东方锦绣兆强盛》

#5楼    回复  引用  查看    

2007-02-28 22:44 by Jeffrey Zhao      
嗯,没有把它当作设计模式理解,以前在Refactoring这本书里接触过。

#6楼    回复  引用  查看    

2007-02-28 22:57 by 木野狐      
《敏捷...》那本书里面也把 Null Object 列为设计模式之一。其实模式本来也不限于23种,有很多未纳入 Gof 那本书范畴的模式。

#7楼    回复  引用  查看    

2007-02-28 23:18 by Jeffrey Zhao      
@木野狐
其实我倒没有什么限制了,只是对于什么样的能够称之为设计模式有待考究。设计模式要是严格论证过的东西,不能光是一个实现或实践的东西。
GoF描写模式的“模板”死板了点,不过很严谨啊。

#8楼    回复  引用  查看    

2007-03-01 00:29 by 木野狐      
hehe,的确,仅满足应用和著述论文的高度是不一样的。

#9楼    回复  引用  查看    

2007-03-01 09:25 by Icebird      
public IEsfLogger EsfLogger
{
set
{
esfLogger = value ?? new EmptyEsfLogger();
}
}

#10楼    回复  引用  查看    

2007-03-01 09:30 by Jeffrey Zhao      
@Icebird
嗯,的确不太合理。
Null Object大都应该是Immutable的……

#11楼    回复  引用    

2007-03-01 19:29 by bwzy [未注册用户]
to:lz

ESFramework.Core.BaseHook.CaptureReceivedMsg方法最后是不是该

return this.DoTranslateReceived(msg);

以及ContainerStyleHook类中

#12楼    回复  引用  查看    

2007-03-02 09:00 by flyingchen      
http://www.cnblogs.com/flyingchen/archive/2007/01/02/610214.html

#13楼    回复  引用    

2007-03-02 16:31 by Andrew Xu [未注册用户]
似乎和 GoF 中的 flyweight 模式很接近。

#14楼    回复  引用  查看    

2007-03-02 18:28 by 阿齐      
@Andrew Xu
这个跟flyweight完全是两码事呢

#15楼    回复  引用    

2007-03-05 12:38 by 生米煮成稀饭 [未注册用户]
那不是很麻烦啊,什么都要多一个同样的空类,有没有更简洁有效的方法

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
"五向定位"职业成长路线公开课(上海、南京、大连)
Google站内搜索


相关链接: