gpt4 book ai didi

c# - 装饰器模式,通过继承还是依赖注入(inject)?

转载 作者:太空狗 更新时间:2023-10-29 23:20:11 24 4
gpt4 key购买 nike

现在我正在研究常见的设计模式,并且在很大程度上我了解装饰器模式的目的。但我不明白的是,将现有对象包装在装饰器类中的目的是什么?

考虑这种情况,因为 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 IProgress<T> 的不同实现界面。

为了这个例子,让我们考虑两种实现方式:

  • EndpointProgress<T> ,这将轮询一个端点和 Report每次的 react 都不一样。
  • 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>());

编辑:

So in a scenario were I am certain I will not extend a class more than once to add functionality, is it acceptable to not use a wrapper?

出于以下几个原因,我仍然会使用装饰器的第二个实现(我什至不确定第一个实现是否会被视为装饰器模式):

  • S.O.L.I.D.原则' open/closed principle指出:

    Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.

    我必须修改当前的 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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com