C#设计准则-基于字符串值调用适当的方法

本文关键字:值调用 字符串 方法 | 更新日期: 2023-09-27 18:30:01

为以下问题寻找设计指南。我收到两个字符串值-action和message,必须调用处理字符串消息的适当方法(processM1MessageVer1、processM1MessageVer2、processM2MessageVer1…)。我必须调用的方法取决于给定的字符串操作。每种处理方法有两个版本(但将来可能会有更多)。我必须调用的方法的版本由全局变量版本决定。每个方法都返回不同类型的对象(ResultObject1、ResultObject2…)。结果必须序列化、转换为base64并返回。

有没有更优雅的写作方式(消除重复代码,使未来可能的更改更容易,减少代码…):

    string  usingVersion = "ver1";
    public string processRequest(string action, string message)
        if (usingVersion == "ver1"){
            processRequestVer1(action, message);
        }
        else{
            processRequestVer2(action, message);
        }
    }    
    //version 1
    public string processRequestVer1(string action, string message){
        string result = "";
        switch (action){
            case "m1":
                ResultObject1 ro = processM1MessageVer1(message);
                result = serialize(ro);
                result = convertToB64(result);
            case "m2":
                ResultObject2 ro = processM2MessageVer1(message);
                result = serialize(ro);
                result = convertToB64(result);
            case "m3":
                ResultObject3 ro = processM3MessageVer1(message);
                result = serialize(ro);
                result = convertToB64(result);      
        }
        return result;
    }
    //version 2
    public string processRequestVer2(string action, string message){
        string result = "";
        switch (action){
            case "m1":
                ResultObject1 ro = processM1MessageVer2(message);
                result = serialize(ro);
                result = convertToB64(result);
            case "m2":
                ResultObject2 ro = processM2MessageVer2(message);
                result = serialize(ro);
                result = convertToB64(result);
            case "m3":
                ResultObject3 ro = processM3MessageVer2(message);
                result = serialize(ro);
                result = convertToB64(result);      
        }
        return result;
    }

如果必须处理的消息是不同的对象类型而不是字符串,这样就可以以多态的方式调用适当的方法,这将更加简单。事实上,每个进程方法都返回不同的对象类型,这也使事情变得更加复杂。但这些不取决于我,我无法更改它。

C#设计准则-基于字符串值调用适当的方法

我的方法(使其更加面向对象,您应该根据处理逻辑的复杂程度来证明创建类结构是否合适。如果您的处理逻辑很小,那么这可能是过度工程):

对于序列化和转换到base64,我假设您有一些逻辑来以通用的方式执行这些任务。如果没有,也将其移动到子类

 public interface IRequestProcessorFactory
{
    IRequestProcessor GetProcessor(string action);
}
public class FactoryVersion1 : IRequestProcessorFactory
{
    public IRequestProcessor GetProcessor(string action)
    {
        switch(action)
        {
            case "m1":
                return new M1Ver1RequestProcessor();
            case "m2":
                return new M2Ver1RequestProcessor();
            case "m3":
                return new M3Ver1RequestProcessor();
            default:
                throw new NotSupportedException();
        }
    }
}
public class FactoryVersion2 : IRequestProcessorFactory
{
    public IRequestProcessor GetProcessor(string action)
    {
        switch(action)
        {
            case "m1":
                return new M1Ver2RequestProcessor();
            case "m2":
                return new M2Ver2RequestProcessor();
            case "m3":
                return new M3Ver2RequestProcessor();
            default:
                throw new NotSupportedException();
        }
    }
}
public interface IRequestProcessor
{
    string ProcessRequest(string message);
}
public class RequestProcessorBase<T>
{
    public string ProcessRequest(string message)
    {
        T result = Process(message);
        string serializedResult = Serialize(result);
        return ConvertToB64(serializedResult);
    }
    protected abstract T Process(string message);
    private string Serialize(T result)
    {
        //Serialize
    }
    private string ConvertToB64(string serializedResult)
    {
        //Convert
    }
}
public class M1Ver1RequestProcessor : RequestProcessorBase<ResultObject1>
{
    protected ResultObject1 Process(string message)
    {
        //processing
    }
}
public class M2Ver1RequestProcessor : RequestProcessorBase<ResultObject2>
{
    protected ResultObject2 Process(string message)
    {
        //processing
    }
}
public class M3Ver1RequestProcessor : RequestProcessorBase<ResultObject3>
{
    protected ResultObject3 Process(string message)
    {
        //processing
    }
}
public class M1Ver2RequestProcessor : RequestProcessorBase<ResultObject1>
{
    protected ResultObject1 Process(string message)
    {
        //processing
    }
}
public class M2Ver2RequestProcessor : RequestProcessorBase<ResultObject2>
{
    protected ResultObject2 Process(string message)
    {
        //processing
    }
}
public class M3Ver2RequestProcessor : RequestProcessorBase<ResultObject3>
{
    protected ResultObject3 Process(string message)
    {
        //processing
    }
}

用法:

string action = "...";
string message = "...";
IRequestProcessorFactory factory = new FactoryVersion1();
IRequestProcessor processor = factory.GetProcessor(action);
string result = processor.ProcessRequest(message);

开关仍然在工厂类中,但它只返回处理器,不做实际工作,所以对我来说很好

首先定义最适合您的接口,比如这个

    public interface IProcessMessage
    {
        string ActionVersion { get; }
        string AlgorithmVersion { get; }
        string ProcessMessage(string message);
    }

然后根据需要创建尽可能多的实现

public class processorM1Ver1 : IProcessMessage
{
    public string ProcessMessage(string message)
    {
        ResultObject1 ro1 = processM1MessageVer1(message);
        var result = serialize(ro1);
        result = convertToB64(result);
        return result;
    }
    public string ActionVersion {get { return "m1"; }}
    public string AlgorithmVersion {get { return "ver1"; }}
}
public class processorM2Ver1 : IProcessMessage
{
    public string ActionVersion {get { return "m2"; }}
    public string AlgorithmVersion {get { return "ver1"; }}
    public string ProcessMessage(string message)
    {
        ResultObject1 ro1 = processM2MessageVer1(message);
        var result = serialize(ro1);
        result = convertToB64(result);
        return result;
    }
}
public class processorM1Ver2 : IProcessMessage
{
    public string ActionVersion {get { return "m1"; }}
    public string AlgorithmVersion {get { return "ver2"; }}
    public string ProcessMessage(string message)
    {
        ResultObject1 ro1 = processM1MessageVer2(message);
        var result = serialize(ro1);
        result = convertToB64(result);
        return result;
    }
}

现在,您需要知道在当前情况下哪个实现是最佳的

public class MessageProcessorFactory
{
    private MessageProcessorFactory() { }
    private static readonly MessageProcessorFactory _instance = new MessageProcessorFactory();
    public static MessageProcessorFactory Instance { get { return _instance; }}
    private IEnumerable<IProcessMessage> _processorCollection;
    IEnumerable<IProcessMessage> ProcessorCollection
    {
        get
        {
            if (_processorCollection == null)
            {
                //use reflection to find all imlementation of IProcessMessage
                //or initialize it manualy
                _processorCollection = new List<IProcessMessage>()
                {
                    new processorM1Ver1(),
                    new processorM2Ver1(),
                    new processorM1Ver2()
                };
            }
            return _processorCollection;
        }
    } 
    internal IProcessMessage GetProcessor(string action)
    {
        var algorithVersion = ReadAlgorithVersion();
        var processor = ProcessorCollection.FirstOrDefault(x => x.AlgorithmVersion == algorithVersion && x.ActionVersion == action);
        return processor;
    }
    private string ReadAlgorithVersion()
    {
        //read from config file
        //or from database
        //or where this info it is kept
        return "ver1";
    }
}

它可以这样使用

public class Client
{
    public string ProcessRequest(string action, string message)
    {
        IProcessMessage processor = MessageProcessorFactory.Instance.GetProcessor(action);
        return processor.ProcessMessage(message);
    }
}