使用装饰器模式分离职责


 我们因为安全、调试或是其他的什么原因,经常需要在我们的程序中插入记录日志的代码,在MS 的 Enterprise Library中, 也提供了日志程序块,由此可见,日志对于任何一个系统都是很重要的。

 通常,我们记录的做法是这样的

    class Business
    
{
        
public virtual void DoSomeWork ()
        
{
            
try
            
{
                
//一些处理业务的代码

                
// 写操作成功日志
            }

            
catch
            
{
                
// 写操作失败日志
                throw;
            }

        }

}

当然,假设我们使用工厂来创建业务对象。  

class BusinessFactory
    
{
        
public static Business CreateBusiness(bool needLog)
        
{            
            
return new Business(needLog);            
        }

}

调用代码           

Business biz = BusinessFactory.CreateBusiness(false);
            
biz. DoSomeWork ();

 

 这些代码工作的很好,但是我们不难发现,我们写日志的代码夹杂在业务逻辑代码之中,而且,我们为了记录业务执行失败的情况,甚至在其中插入了本来可能不必要的异常处理—try/catch块。这使我们的业务逻辑代码变得臃肿而且难以维护。

 记住 Fowler 告诉我们的:重构以使用模式。经过一段时间的冥思苦想,我发现 Decorator 模式正是用于解决此问题。重构的目的是将日志记录代码从业务逻辑代码中分离,重构步骤如下:


1、 新建一个 装饰类 ,从 Business 继承,并覆写其中的DoSomeWork 方法。
2、 将 异常处理和日志记录移至 派生类 中,使派生类中覆写的方法调用基类中的方法。
3、 更改工厂,使其返回派生类的实例。

重构以后的代码

业务类: 

class Business
    
{
        
public virtual void DoSomeWork()
        
{
           
//一些处理业务的代码
        }

}


业务的装饰类

   

class LoggedBusiness : Business
    
{
        
private Business biz;

        
public LoggedBusiness(Business biz)
        
{
            
this.biz = biz;
        }


        
public override void DoSomeWork()
        
{
            
try
            
{
                biz.DoSomeWork();
                
// 写成功日志
            }

            
catch
            

                
// 写失败日志
                throw;
            }

        }

    }

工厂

public static Business CreateBusiness(bool needLog)
    
{
            Business biz 
= new Business();
            
if( needLog )
              
return new LoggedBusiness(biz);
            
else
              
return biz ;
    }

工厂的使用者,根本没有意识到,他所使用的对象已经悄悄的发生了改变。这也正是 装饰器 模式的优点 --- 对象的使用者根本不知道他所使用的对象已经被装饰了,但装饰器已经开始工作了。另外,我们可以在运行的时候决定是否使用 装饰类,只要稍稍修改工厂--在工厂中根据上下文判断是返回装饰类还是原始类的实例--就可以了。我们可以对对象使用多重装饰,以使其具有多重职责,这一点也很有用。


个人认为,装饰器的作用在于通过扩展的方式把附加的职责添加到原始对象上,本文介绍的只是它的一个小小的应用。
也有人认为,凡是需要用到装饰器模式的地方,都是需要三段话都是需要使用AOP的地方。AOP带来了代码的优雅,然而使用AOP却是有代价的,效率的或者是其他的代价。

posted @ 2005-12-13 18:25  quitgame  阅读(848)  评论(0编辑  收藏  举报