Amb*_*dex 5 c# design-patterns decorator
现在我正在研究常见的设计模式,并且在很大程度上我理解了装饰模式的目的.但我没有得到的是,在装饰器类中包装现有对象的目的是什么?
考虑这种情况,因为Progress是观察者模式的一部分,我想限制其订阅者的更新量以防止UI线程锁定.
所以我把类修饰为每50毫秒只更新一次.
public class ProgressThrottle<T> : Progress<T>
{
private DateTime _time = DateTime.Now;
public ProgressThrottle(Action<T> handler) : base(handler)
{
}
protected override void OnReport(T value)
{
if (DateTime.Now.AddMilliseconds(50) < _time)
{
base.OnReport(value);
_time = DateTime.Now;
}
}
}
public class ProgressThrottle2<T> : IProgress<T>
{
private DateTime _time = DateTime.Now;
private readonly IProgress<T> _wrapper;
public ProgressThrottle2(IProgress<T> wrapper)
{
_wrapper = wrapper;
}
public void Report(T value)
{
if (DateTime.Now.AddMilliseconds(50) < _time)
{
_wrapper.Report(value);
_time = DateTime.Now;
}
}
Run Code Online (Sandbox Code Playgroud)
这两个类完成相同的事情,除了我发现第一个版本更好,因为它允许我使用基础构造函数来设置进度更新的委托.基类已经支持覆盖该方法,那么我需要包装对象是什么?
这两个类都是装饰器模式的例子吗?我宁愿使用第一个选项,但我很少以这种方式看到例子.
想象一下您有n不同的接口实现IProgress<T>。
为了这个例子,让我们考虑两种实现:
\n\nEndpointProgress<T>,这将轮询端点并且Report每次响应都不同。QueryProgress<T>,这将定期执行数据库查询,并且Report每次结果都不同。为了使用第一种方法限制这两种实现,您必须创建 的两个实现ProgressThrottle<T>,一个继承自EndpointProgress<T>,另一个继承自QueryProgress<T>。
为了使用第二种方法来限制这两种实现,您只需使用EndpointProgress<T>和的包装实例QueryProgress<T>。
var throttledEndpointProgress = new ProgressThrottle2<int>(new EndpointProgress<T>());\nvar throttledQueryProgress = new ProgressThrottle2<int>(new QueryProgress<T>());\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n\n因此,在我确信我不会多次扩展一个类来添加功能的情况下,不使用包装器是否可以接受?
\n
我仍然会使用装饰器的第二个实现(我什至不确定第一个实现是否会被视为装饰器模式),原因如下:
\n\nS.O.LID原则的开放/封闭原则指出:
\n\n\n\n\n软件实体(类、模块、函数等)应该对扩展开放,但对修改关闭。
\n
如果您必须修改当前的Progress实现才能扩展它,那么您违反了开放/封闭。
继承ProgressThrottle自Progress意味着每次Progress构造函数更改时,ProgressThrottle也需要更改其构造函数。
通过使用包装装饰器,您可以组合和组合装饰器。让我们考虑一个IProgress<T>记录每个onReport调用的实现。你可以根据配置、环境等 xe2x80x94 以不同的方式组合这些装饰器来实现不同的目标:
var progress1 = new LoggingProgress<int>(\n new ProgressThrottle<int>(new Progress<int>())\n);\nvar progress2 = new ProgressThrottle<int>(\n new LoggingProgress<int>(new Progress<int>())\n);\nRun Code Online (Sandbox Code Playgroud)\n\n此处,progress1将仅记录受限制的报告进度。progress2将记录所有报告的进度,但将以限制方式报告。根据您的目标,您可能需要一种实现或另一种实现;或者您可能需要两者,一个用于暂存中的诊断,另一个用于生产,但最重要的是您不必更改装饰器的实现来更改此行为。