Как избежать длительного переключения .. нужна помощь в рефакторинге - PullRequest
2 голосов
/ 23 декабря 2009

Мне нужна помощь в рефакторинге следующего класса,

Ниже приведен класс Операция с различными операциями в коммутаторе: Я хочу избежать оператора switch. Я прочитал несколько статей об использовании полиморфизма и паттерна состояния. Но когда я реорганизую классы, я не получаю доступ ко многим переменным, свойства
Я не понимаю, использовать ли операцию как абстрактный класс или реализовать интерфейс.
Просто хотел узнать, какой тип рефакторинга поможет в этом случае
полиморфизм или картина состояния?
И когда их использовать?

public class Operation
    {
        public enum OperationType
        {
            add,
            update,
            delete,
            retrieve
        }
        public enum OperationStatus
        {
            Success,
            NotStarted,
            Error,
            Fail,
            InProcess,
            Free
        }

    // raise this event when operation completes
    public delegate void OperationNotifier(Operation operation);
    public event OperationNotifier OperationEvent=null;           

    private OperationStatus _status=OperationStatus.Free;
    public OperationStatus Status
    {
        get { return _status; }
        set { _status = value; }
    }      


    private string _fileName = null;

    public string FileName
    {
        get { return _fileName; }
        set { _fileName = value; }
    }

    private string _opnid = null;

    public string OperationId
    {
        get { return _opnid; }
        set { _opnid = value; }
    }

    private OperationType _type;
    public OperationType Type
    {
        get { return _type; }
        set { _type = value; }
    }

   public void performOperation(OperationType type, string parameters)
    {  

        switch (type)
        {
            case OperationType.add:
                _status = addOperation(parameters);                   
                break;
            case OperationType.update:
               _status = updateOperation(parameters);
                break;
            case OperationType.delete:
                _status = deleteOperation(parameters);
                break;
            case OperationType.retrieve:
                _status = retrieveOperation(parameters);
                break;
            default:
                break;
        }
        if (OperationEvent != null)
            OperationEvent(this);           
       // return true;
    }


    public OperationStatus addOperation(string parameters)
    {           
        DateTime start = DateTime.Now;
         //Do SOMETHING BIG
        TimeSpan timeTaken = DateTime.Now - start;
        System.Diagnostics.Debug.WriteLine("addOperation:-" + _opnid + "-" + _fileName + "--" + timeTaken.Milliseconds); 
        return OperationStatus.Success;

        }
...other operations here....

Телефонный код похож на:

  Operation oprnObj;
                Operation.OperationType operationType;

 oprnObj = new Operation();
 oprnObj.FileName = String.Concat("myxmlfile",".xml");
 oprnObj.OperationId = oprnid;
 oprnObj.OperationEvent += new Operation.OperationNotifier(oprnObj_OperationEvent);
 operation="add"; //get From Outside function getOperation()
 operationType = (Operation.OperationType)Enum.Parse(typeof(Operation.OperationType),   operation.ToLower(), true);
 oprnObj.Type = operationType;
 oprnObj.performOperation(operationType, parameters);

Ссылки Темы:
Ссылка
Ссылка
..Много больше.

Ответы [ 4 ]

4 голосов
/ 23 декабря 2009

Если вы ищете шаблоны, то я думаю, что вы должны проверить шаблон стратегии и шаблон цепочки ответственности.

http://en.wikipedia.org/wiki/Strategy_pattern

http://en.wikipedia.org/wiki/Chain_of_responsibility_pattern

Оба из них могут быть полезны для понимания этого кода.

2 голосов
/ 23 декабря 2009

В C # вы можете использовать функции для стратегии и использовать метод расширения, поскольку функция дает вам возможность добавлять операции по мере необходимости:

public enum OperationStatus
{
    Success, NotStarted, Error, Fail, InProcess, Free
}

public class Operation
{
    // raise this event when operation completes
    public delegate void OperationNotifier(Operation operation, OperationStatus status);
    public event OperationNotifier OperationEvent = null;

    public string FileName { get; set; }
    public string OperationId { get; set; }

    public Func<string, OperationStatus> Function { get; set; }

    public void PerformOperation(string parameters)
    {
        OperationStatus status = Function(parameters);

        if (OperationEvent != null)
            OperationEvent(this, status);
    }
}

static class AddOp
{
    public static OperationStatus AddOperation(this Operation op, string parameters)
    {
        DateTime start = DateTime.Now;
        //Do SOMETHING BIG
        TimeSpan timeTaken = DateTime.Now - start;
        System.Diagnostics.Debug.WriteLine("addOperation:-" + op.OperationId + "-" + op.FileName + "--" + timeTaken.Milliseconds);
        return OperationStatus.Success;
    }
}

class Program
{
    static void Main(string[] args)
    {
        Operation oprnObj = new Operation();
        oprnObj.FileName = String.Concat("myxmlfile", ".xml");
        oprnObj.OperationId = "oprnid";
        oprnObj.OperationEvent += new Operation.OperationNotifier(oprnObj_OperationEvent);
        string parameters = "fish";
        oprnObj.Function = oprnObj.AddOperation;
        oprnObj.PerformOperation(parameters);
    }

    public static void oprnObj_OperationEvent(Operation op, OperationStatus status)
    {
        Console.WriteLine("{0} returned {1}", op.Function.Method.Name, status);
    }
}

Вы также можете передать OperationEvent в функцию, если вы хотите промежуточные обновления статуса.

1 голос
/ 23 декабря 2009

Я думаю, что вы на правильном пути, пытаясь использовать здесь полиморфизм. Это должно привести вас к шаблону Strategy . Преобразуйте определенные операции в подклассы (AddOperation и т. Д.), А также (и это, вероятно, пропущенный шаг), выделите data (имя файла и т. Д.) В отдельный объект, который передается к каждой операции.

Я бы создал как интерфейс Operation, так и OperationBase, который бы содержал статус.

0 голосов
/ 23 декабря 2009

Я бы хотел, чтобы вы проверили, может ли этот случай переключения появляться в нескольких местах. Если он просто изолирован в одном месте, вы можете жить с этим. (Альтернативы являются более сложными).

Однако, если вам нужно внести изменения,
Посетите следующую ссылку - http://refactoring.com/catalog/index.html
Ищите «Заменить код типа», есть 3 возможных рефакторинга, которые вы можете использовать. ИМХО Стратегия одна - это та, которая тебе нужна.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...