首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >责任链绩效

责任链绩效
EN

Stack Overflow用户
提问于 2014-07-19 18:20:13
回答 1查看 525关注 0票数 2

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

代码语言:javascript
复制
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_3、....Operation_N,可能在11到15个类之间,但现在只有Operation_1和Operation_2。如果我想添加Operation_3,那么我必须更新OperationService类,添加一个新的方法:Exec_Operation_3(数据)。

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

代码语言:javascript
复制
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)

代码语言:javascript
复制
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实例-in (第一个解决方案)是有点重的对象,OperationCaller创建了其中的许多对象,因此我对此有疑问,我不知道这个实现/解决方案是否会有性能问题。

你怎么认为。在本例中,使用CoR会出现性能问题吗?如果不是,第一个(解决方案1)还是最后一个(解决方案2)更好?

EN

回答 1

Stack Overflow用户

发布于 2016-03-19 09:25:35

在本例中,使用CoR会出现性能问题吗?

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

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

这些性能问题是由于IOperation违反了单责任原则,并将操作查找算法CanExecute与操作执行算法ExecOperation相结合。每次您想要进行操作查找时,都必须创建执行算法。

在解决方案2中,通过使用代理类Operation将包含在CoROperation类中的执行算法与查找算法解耦,但这带来了复杂性。

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

解决方案是制作一个由OperationType散列的操作构造函数的字典。

代码语言:javascript
复制
dim Dictionary as new Dictionary(of String, Func(of Data, IOperation))

字典提供查找算法。

操作构造函数确定如何获得操作,并提供指定操作生存期的能力。

例如,

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

然后

代码语言:javascript
复制
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 of OperationCaller类通过字典查找合适的操作构造函数,获取并执行操作。

优点:

  1. 由于字典的存在,操作查找时间是恒定的,并且与操作计数无关。
  2. 非常灵活的控制每个操作生存期的方法,为缓存操作和/或推迟大量操作的创建提供了机制。

缺点:

  1. Lambda函数
  2. 如果没有明确的操作鉴别器,则必须使用模式匹配而不是字典。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24843559

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档