现在,我正在研究常见的设计模式,并且在很大程度上,我了解了装饰器模式的目的。但是我不明白的是,将现有对象包装在装饰器类中的目的是什么?
考虑这种情况,因为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;
}
}
除了我发现第一个版本更好之外,这两个类都完成相同的事情,因为它允许我使用基本构造函数为进度更新设置委托(delegate)。基类已经支持重写方法,那么我包装对象有什么需要?
这两个类都是装饰器模式的示例吗?我宁愿使用第一个选项,但我很少看到这种方式的示例。
最佳答案
假设您有n
接口(interface)的IProgress<T>
不同实现。
为了这个示例,让我们考虑两个实现:
EndpointProgress<T>
,这将在每次响应不同时轮询一个端点和Report
。 QueryProgress<T>
,这将定期执行数据库查询,每次结果不同时都会执行Report
。 为了使用第一种方法限制这两种实现,您必须创建
ProgressThrottle<T>
的两个实现,一个从EndpointProgress<T>
继承,另一个从QueryProgress<T>
继承。为了使用第二种方法限制这两种实现,您只需要使用包装的
EndpointProgress<T>
和QueryProgress<T>
实例即可。var throttledEndpointProgress = new ProgressThrottle2<int>(new EndpointProgress<T>());
var throttledQueryProgress = new ProgressThrottle2<int>(new QueryProgress<T>());
编辑:
我仍然会使用装饰器的第二个实现(我什至不确定第一个实现是否会被视为装饰器模式),原因如下:
如果您要扩展它,则必须修改当前的
Progress
实现,这违反了“打开/关闭”。 ProgressThrottle
继承Progress
意味着每次Progress
'构造函数更改时,ProgressThrottle
也需要更改其构造函数。 IProgress<T>
的实现,该实现记录每个onReport
调用。您可以根据配置,环境等以不同的方式组合这些装饰器,以实现不同的目标:var progress1 = new LoggingProgress<int>(
new ProgressThrottle<int>(new Progress<int>())
);
var progress2 = new ProgressThrottle<int>(
new LoggingProgress<int>(new Progress<int>())
);
在这里,
progress1
将仅记录受限制的报告进度。 progress2
将记录所有报告的进度,但是将以节流的方式报告。根据您的目标,您可能需要一个实现或另一个实现;或者您可能想要它们两者,一个用于登台诊断,另一个用于生产,但是最重要的是,您不必更 retrofit 饰器的实现即可更改此行为。 关于c# - 装饰器模式,通过继承还是依赖注入(inject)?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47746295/