技术开发 频道

结构型模式篇-装饰模式(Decorator Pattern)


    在软件开发中,经常会遇到动态地为一个对象而不是整个类增加一些功能的问题,还是以我惯用的记录日志的例子来说明吧(也许在Decorator模式里面用这个例子不是特别合适)。现在要求我们开发的记录日志的组件,除了要支持数据库记录DatabaseLog和文本文件记录TextFileLog两种方式外,我们还需要在不同的应用环境中增加一些额外的功能,比如需要记录日志信息的错误严重级别,需要记录日志信息的优先级别,还有日志信息的扩展属性等功能。在这里,如果我们不去考虑设计模式,解决问题的方法其实很简单,可以通过继承机制去实现,日志类结构图如下:



                                      图3

实现代码如下:

public abstract class Log { public abstract void Write(string log); } public class DatabaseLog : Log { public override void Write(string log) { //......记录到数据库中 } } public class TextFileLog : Log { public override void Write(string log) { //......记录到文本文件中 } }
    需要记录日志信息的错误严重级别功能和记录日志信息优先级别的功能,只要在原来子类DatabaseLog和TextFileLog的基础上再生成子类即可,同时需要引进两个新的接口IError和I Priority,类结构图如下:


                                                                                        图4

实现代码如下:

public interface IError { void SetError(); } public interface IPriority { void SetPriority(); } public class DBErrorLog : DatabaseLog, IError { public override void Write(string log) { base.Write(log); } public void SetError() { //......功能扩展,实现了记录错误严重级别 } } public class DBPriorityLog : DatabaseLog, IPriority { public override void Write(string log) { base.Write(log); } public void SetPriority() { //......功能扩展,实现了记录优先级别 } } public class TFErrorLog : TextFileLog, IError { public override void Write(string log) { base.Write(log); } public void SetError() { //......功能扩展,实现了记录错误严重级别 } } public class TFPriorityLog : TextFileLog, IPriority { public override void Write(string log) { base.Write(log); } public void SetPriority() { //......功能扩展,实现了记录优先级别 } }
    此时可以看到,如果需要相应的功能,直接使用这些子类就可以了。这里我们采用了类的继承方式来解决了对象功能的扩展问题,这种方式是可以达到我们预期的目的。然而,它却带来了一系列的问题。首先,前面的分析只是进行了一种功能的扩展,如果既需要记录错误严重级别,又需要记录优先级时,子类就需要进行接口的多重继承,这在某些情况下会违反类的单一职责原则,注意下图中的蓝色区域:



                                                                                           图5

实现代码:

public class DBEPLog : DatabaseLog, IError, IPriority { public override void Write(string log) { SetError(); SetPriority(); base.Write(log); } public void SetError() { //......功能扩展,实现了记录错误严重级别 } public void SetPriority() { //......功能扩展,实现了记录优先级别 } } public class TFEPLog : DatabaseLog, IError, IPriority { public override void Write(string log) { SetError(); SetPriority(); base.Write(log); } public void SetError() { //......功能扩展,实现了记录错误严重级别 } public void SetPriority() { //......功能扩展,实现了记录优先级别 } }




0
相关文章