首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > .NET >

装饰器模式的有关问题

2012-12-26 
装饰器模式的问题我有一个抽象类abstract class Log{public string messageabstract public void Write()

装饰器模式的问题
我有一个抽象类
abstract class Log
{
    public string message;
    abstract public void Write();
}
和一个实体类
class TextLog : Log
{
    public override void Write()
    {
        Console.WriteLine(message);
    }
}
我想编写两个装饰类PriorityLog和ErrorLog,能够对一个Log进行装饰,
能够实现如下结果
TextLog log=new TextLog();
t.message="删除用户";
t.Write();
打印结果为:删除用户

PriorityLog plog=new Priority(log);
plog.level=1;
plog.Write();
打印结果为:删除用户,优先级别:1

ErrorLog elog=new ErrorLog(plog);
elog.level=2;
elog.Write();
打印结果为:删除用户,优先级别:1,错误级别:2

用装饰器模式如何实现?请高手指教!!

[解决办法]

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            TextLog log = new TextLog();
            log.message = "删除用户";
            log.Write();

            PriorityLog plog = new PriorityLog(log);
            plog.level = 1;
            plog.Write();

            ErrorLog elog = new ErrorLog(plog);
            elog.level = 2;
            elog.Write();

            Console.ReadKey();
        }
    }


    abstract class Log
    {
        public string message;
        abstract public void Write();
    }
    class TextLog : Log
    {
        public override void Write()
        {
            Console.WriteLine();
            Console.Write(message);
        }
    }

    class PriorityLog : Log
    {
        Log _log;
        public int? level;

        public PriorityLog(Log log)
        {
            _log = log;
        }



        public override void Write()
        {
            _log.Write();
            Console.Write(",优先级别:"+level??0.ToString());
        }
    }

    class ErrorLog : Log
    {
        Log _log;
        public int? level;
        public ErrorLog(Log log)
        {
            _log = log;
        }

        public override void Write()
        {
            _log.Write();
            Console.Write(",错误级别:"+level??0.ToString());
        }
    }
}


[解决办法]
事件驱动编程是非常基本和广泛使用的软件设计思路,是非常简单的流程扩展思路。

仅仅为了稍微扩展一点事件处理,就绕出去好远搞了好几个新的类型出来然后相互依赖,搞了一堆复杂的概念流程,还硬说这种是好的设计模式,我想只有GOF做得出来。

在GOF写出了所谓的设计模式很多年,java里边又掀起一股完全相反的阴风,说什么AOP仅用“一招模式”就可以替代GOF的几乎90%设计模式了。实际上AOP则更加混乱。因为它不是如上那样让设计人员主动暴露事件接口,而是要在编译器底层去动手脚去强行加入事件代码,编译出来的程序非常难以调试(因为连调试器都无法正常工作了,因为编译之后的代码又被人家动了手脚了,所以调试器也就乱了)。
[解决办法]
C#对装饰模式有语言级别的支持,这就是扩展方法:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    abstract class Log
    {
        public string Message { get; set; }
        abstract public void Write();
    }

    class TextLog : Log
    {
        public override void Write()
        {
            Console.WriteLine(Message);
        }
    }

    static class LogDecorator
    {
        //C#的扩展方法不支持扩展属性,但是未来据说要增加这个特性。所以增加以下代码来模拟扩展属性。
        #region ExtendFields
        private static Dictionary<Log, int[]> ExtendFields = new Dictionary<Log,int[]>();

        private static void SetValue(this Log log, int value, int index)
        {
            if (!ExtendFields.ContainsKey(log))
                ExtendFields.Add(log, new int[] { 0, 0 });
            ExtendFields[log][index] = value;


        }
        private static int GetValue(this Log log, int index)
        {
            if (!ExtendFields.ContainsKey(log))
                ExtendFields.Add(log, new int[] { 0, 0 });
            return ExtendFields[log][index];
        }
        #endregion

        public static void SetPriority(this Log log, int value)
        {
            log.SetValue(value, 0);
        }

        public static int GetPriority(this Log log)
        {
            return log.GetValue(0);
        }

        public static void SetErrorLevel(this Log log, int value)
        {
            log.SetValue(value, 1);
        }

        public static int GetErrorLevel(this Log log)
        {
            return log.GetValue(1);
        }

        //C#的扩展方法不支持覆盖方法,所以不得不另外使用一个函数名,不过这么做也有好处,明确调用的是扩展方法版本。
        public static void WriteWithPriorityAndErrorLevel(this Log log)
        {
            Console.WriteLine("{0},优先级别:{1},错误级别:{2}。", log.Message, log.GetPriority(), log.GetErrorLevel());
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            TextLog tl = new TextLog() { Message = "删除用户" };
            tl.SetPriority(1);
            tl.SetErrorLevel(2);
            tl.WriteWithPriorityAndErrorLevel();
        }
    }
}

热点排行