我有要修改的代码以应用责任链(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)。

我看到所有方法都返回相同的类型(Response)并以相同的类型(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)?

最佳答案

在这种情况下,使用CoR会有性能问题?


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


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


这些性能问题来自于以下事实:IOperation违反了单一职责原则,并将操作查找算法CanExecute与操作执行算法ExecOperation耦合。每次您要进行操作查找时,都必须创建执行算法。

在解决方案2中,使用代理类OperationCoROperation类中包含的执行算法与查找算法分离,但这会带来复杂性。

在该示例中,有一个清晰的鉴别符OperationType可用于操作查找。

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

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


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

优点:


借助字典,操作查找时间是恒定的,并且与操作计数无关
控制每个操作生命周期的非常灵活的方法提供了缓存操作和/或推迟繁重的操作创建的机制


缺点:


Lambda函数
如果没有明确的操作区分符,则必须使用模式匹配而不是字典

关于c# - 责任链绩效,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24843559/

10-09 03:12