课堂设计问题

时间:2010-09-02 06:18:49

标签: c# .net delegates

用简洁的语言表达......

目的:
创建一个可以在数据源中加载和保存对象列表的类。

当前方法:
我创建了一个接受两个委托作为构造参数的类:

private class Foo
{
    public delegate List<object> LoadObjectsDelegate();
    public delegate void SaveObjectsDelegate(List<object> data);

    private LoadObjectsDelegate _loadDelegate;
    private SaveObjectsDelegate _saveDelegate;

    public Foo(LoadObjectsDelegate loadDelegate, SaveObjectsDelegate saveDelegate)
    {
        _loadDelegate = loadDelegate;
        _saveDelegate = saveDelegate;
    }

    public List<object> Objects {get; private set;}

    public void Load()
    {
        Objects = _loadDelegate.Invoke();
    }

    public void Save()
    {
        _saveDelegate.Invoke(Objects);
    }
}

我想知道是否有更清洁的方法来做到这一点。

3 个答案:

答案 0 :(得分:2)

从它的外观来看,我会说你正在尝试实现Repository模式,并具有一些扩展功能。我也认为没有必要尝试注入负载并保存逻辑,因为这是实现它们的存储库工作。如果加载和保存对象的逻辑对于域中的所有对象都是相同的,则将其在基类中实现,并在需要时在派生类中覆盖它。关于SO的This文章可以为您提供有关如何处理此模式的一些想法。

答案 1 :(得分:0)

好吧,有一件事我会把它变成通用的(Foo<T>) - 你的调用者总是可以指定object,如果他们真的需要,这意味着他们可以以更强类型的方式使用它必要的。

目前我不确定这个课程真的会增加很多价值,说实话。它实际上只是将这三个值组合在一起 - 而这就是全部。如果这就是你想要的那样,那很好......但对我来说感觉有点贫血。

答案 2 :(得分:0)

它不是更清洁,只是另一种方法。如果您在代理中指定的行为变化不大,请考虑Template Pattern

private abstract class AbstractFoo
{
    public List<object> Objects { get; private set; }

    public List<object> Load();

    public abstract void Save(List<object> data);

    // add common functionality
}


private class ConcreteFoo : AbstractFoo
{
    public override List<object> Load()
    {
        // do specific stuff
    }

    public override void Save(List<object> data)
    {
        // do specific stuff
    }
}

缺点是每个特定行为都需要一个类。因此:如果委托给出的行为变化很大,或者您需要动态加载不同的行为,我发现您的委托方法是合适的。我通常发现模板模式更容易理解,更容易进行单元测试。

您可以更进一步:行为由模板模式中的继承指定。如果您选择具有接口的更抽象方法,则可以通过引用指定行为,而不是继承:

private interface IRepository
{
    List<object> Load();
    void Save(List<object> data);
}


private class FooBar
{
    private IRepository repository;
    public List<object> Objects { get; private set; }

    public FooBar(IRepository repository)
    {
        this.repository = repository;
    }

    public void Load()
    {
        Objects = repository.Load();
    }

    public void Save()
    {
        repository.Save(Objects);
    }
}

如果您需要某些特定行为,则需要实现从IRepository派生的类。这种方法比模板模式更容易理解和单元测试。我经常最终用后一种方法替换模板模式。