【问题标题】:Chain of Responsibility Performance责任链绩效
【发布时间】:2014-07-19 18:20:13
【问题描述】:

我有想要修改应用责任链 (CoR) 模式的代码,但如果我有很多继任者,我对性能有疑问。 首先,这是没有 CoR 的代码:

public class OperationService
{
    public Response Exec_Operation_1(Data data)
    {
        Operation_1 op = new Operation_1();
        return op.ExecOperation();
    }

    public Response Exec_Operation_2(Data data)
    {
        Operation_2 op = new Operation_2();
        return op.ExecOperation();
    }
}
public class Operation_1
{
    private Data _data;
    public Operation_1(Data data)
    {
        this._data = data;
    }
    public Response ExecOperation()
    {
        //process data. So much code. Many instantiations.
        //Many references to other assemblies.
        //serialize/deserialize xml. Call webservices. 
        return new Response();
    }
}
//Operation_2 class seems like Operation_1 class...

嗯,确实有很多 Operation 类:Operation_3,....Operation_N,可能在 11 到 15 个类之间,但目前只有 Operation_1 和 Operation_2。如果我想添加 Operation_3,那么我必须更新 OperationService 类,添加一个新方法:Exec_Operation_3(Data data)。

我看到所有方法都返回相同的类型(响应)并作为参数接收相同的类型(数据),Operation_1 和 Operation_N 的方法也将具有相同的签名,所以我想我可以这样重写代码: (解决方案1)

public class OperationService
{
    public Response Exec_Operation(Data data)
    {
        OperationCaller caller = new OperationCaller();
        return caller.ExecOperation(data);
    }
}
public class OperationCaller
{
    public Response ExecOperation(Data data)
    {
        IOperation unknownOperation = new UnknownOperation();
        IOperation operation_2 = new Operation_2(unknownOperation);
        IOperation operation_1 = new Operation_1(operation_2);        
        return operation_1.ExecOperation(data);
    }
}
public interface IOperation
{
    bool CanExecute(Data data);
    Response ExecOperation(Data data);
}
public class Operation_1:IOperation
{
    private IOperation _succesor;
    public Operation_1(IOperation succesor)
    {
        this._succesor = succesor;
    }
    public CanExecute(Data data)
    {
        return data.OperationType.equals("1");
    }
    public Response ExecOperation(Data data)
    {
        if(this.CanExecute)
        {
            //process data. So much code. Many instantiations.
            //Many references to other assemblies.
            //serialize/deserialize xml. Call webservices.
            return new Response();
        }
        else
        {
            return this._succesor.ExecOperation(data);
        }
    }
}
//Other IOperation implementations seems like this Operation_1.

如果您看到我正在应用 CoR 模式,那么当我添加新的 Operation_X 类时,我不必修改 OperationService 类,我只需更新 OperationCaller 类。

但在这个解决方案中,我只修改类 Operation_1(和 Operation_2,...,Operation_N),但是这个类的代码太多,阅读起来有点困难,所以我认为最好创建另一个类以使用 CoR,并在该类中创建 Operation_1,..,Operation_N 的实例,如下所示:(解决方案 2)

public class OperationCaller
{
    public Response ExecOperation(Data data)
    {
        IOperation unknownOperation = new CoRUnknownOperation();
        IOperation operation_2 = new CoROperation_2(unknownOperation);
        IOperation operation_1 = new CoROperation_1(operation_2);        
        return operation_1.ExecOperation(data);
    }
}
public interface IOperation
{
    bool CanExecute(Data data);
    Response ExecOperation(Data data);
}
public class CoROperation_1:IOperation
{
    private IOperation _succesor;
    public Operation_1(IOperation succesor)
    {
        this._succesor = succesor;
    }
    public CanExecute(Data data)
    {
        return data.OperationType.equals("1");
    }
    public Response ExecOperation(Data data)
    {
        return (this.CanExecute) ? new Operation_1().ExecOperation(data);
                                 : this._succesor.ExecOperation(data);
    }
}

在最后一个解决方案中我没有修改 Operation_1,我只创建了一个层来解耦 OperationService(这是目标)。

但我认为 Operation_1 实例 - 在最后一个解决方案中 - 或 IOperation 实例 - 在第一个解决方案中 - 是一个有点重的对象,并且 OperationCaller 创建了许多对象,所以我对此表示怀疑,我不知道这是否实施/解决方案会有性能问题。

你怎么看。在这种情况下,我会遇到使用 CoR 的性能问题吗?如果不是,第一个(解决方案 1)或最后一个(解决方案 2)哪个解决方案更好?

【问题讨论】:

  • 试一试,但更重要的是,这点重要吗?通常,只要性能满足您的要求,清晰度就比性能更重要。
  • 谢谢@Arkain,你是对的,清晰更重要,此时性能并不重要。

标签: c# .net design-patterns chain-of-responsibility


【解决方案1】:

在这种情况下,我会遇到使用 CoR 的性能问题吗?

是的,使用责任链时存在性能问题:

  1. 链中的每个操作都会为每个数据调用重新创建
  2. 操作查找时间与操作链长度成正比

这些性能问题源于IOperation 违反单一职责原则并将操作查找算法CanExecute 与操作执行算法ExecOperation 耦合。每次你想进行操作查找时,你都必须创建执行算法。

在解决方案 2 中,您使用代理类 CoROperation 将包含在 Operation 类中的执行算法与查找算法分离,但这会引入复杂性。

在示例中,有一个明确的鉴别器OperationType,可用于操作查找。

解决方案是制作一个由OperationType 散列的操作构造函数Func(of Data, IOperation) 的字典。

dim Dictionary as new Dictionary(of String, Func(of Data, IOperation))

字典提供查找算法。

操作构造函数确定如何获取操作并提供指定操作生命周期的能力。

例如,

  • LightOperation1 独立于数据且不繁重,
  • HeavyOperation2 也独立于数据但很重,应该在需要时创建,
  • InjectedOperation3 也是数据独立和依赖注入
  • DataDependentOpartion4 依赖于数据,必须为新数据重新创建
  • 操作 5 将实际执行调用委托给某些服务

然后

class OperationCaller
    private readonly OperationDictionary as IDictionary(of String, Func(of Data, IOperation))

    public sub new(InjectedOperation3 as IOperation, OperationService as IOperationService)

        dim LightOperation1 as new LightOperation1
        dim HeavyOperation2 as new Lazy(of HeavyOperation2)(function() new HeavyOperation2)

        dim Dictionary as new Dictionary(of String, Func(of Data, IOperation)) from {
            {"1", function(Data) LightOperation1},
            {"2", function(Data) HeavyOperation2.Value},
            {"3", function(Data) InjectedOperation3},
            {"4", function(Data) new DataDependentOperation4(Data)},
            {"5", function(Data) new DelegateOperation(addressof OperationService.Exec_Operation_5)}
        }

        me.OperationDictionary = Dictionary
    end sub

    public function ExecOperation(Data as Data) as Response
        return OperationDictionary(Data.OperationType)(Data).ExecOperation(Data)
    end function
end class

OperationCaller类的方法ExecOperation通过字典找到合适的操作构造函数,获取并执行操作。

优点:

  1. 操作查找时间是恒定的,并且与操作计数无关,这要归功于字典

  2. 控制每个操作生命周期的非常灵活的方法提供了缓存操作和/或推迟创建繁重操作的机制

缺点:

  1. Lambda 函数

  2. 如果没有明确的操作鉴别器,则必须使用模式匹配而不是字典

【讨论】:

    猜你喜欢
    • 2017-08-20
    • 1970-01-01
    • 2020-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-21
    • 1970-01-01
    相关资源
    最近更新 更多