装饰器模式的问题
我有一个抽象类
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();
}
}
}