C#设计指南 - 根据字符串值调用适当的方法

时间:2014-11-12 00:00:04

标签: c# oop design-patterns code-design

寻找以下问题的设计指南。 我收到两个字符串值 - 操作和消息,并且必须调用处理字符串消息的适当方法(processM1MessageVer1,processM1MessageVer2,processM2MessageVer1 ...)。我必须调用的方法取决于给定的字符串操作。每种处理方法有2个版本(但将来可能会有更多)。我必须调用的方法版本由全局变量版本决定。每个方法都返回不同类型的对象(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;
    }

如果必须处理的消息是不同的对象类型而不是字符串,那么可以更简单地调用适当的方法。每个流程方法返回不同对象类型的事实也使事情变得更复杂。但这些并不依赖于我,我也无法改变它。

2 个答案:

答案 0 :(得分:1)

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

对于序列化和转换为base 64,我假设您有一些逻辑以通用方式执行这些任务。如果没有,也将它们移到子类

 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);

开关仍然在工厂类中,但它只返回处理器而不进行实际工作所以对我来说没问题

答案 1 :(得分:0)

首先 - 定义最适合你的界面,比如

    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);
    }
}