2010-04-22 1 views
2

Я пытаюсь применить OCP к фрагменту кода. У меня есть то, что в текущем состоянии это действительно вонючий, но я чувствую, что не добираюсь до конца.Открытое закрытое начало, рефакторинг

Текущий код:

public abstract class SomeObject 
{} 

public class SpecificObject1 : SomeObject 
{} 

public class SpecificObject2 : SomeObject 
{} 


// Smelly code 
public class Model 
{ 
    public void Store(SomeObject someObject) 
    { 
    if (someObject is SpecificObject1) 
    {} 
    else if (someObject is SpecificObject2) 
    {} 
    } 
} 

Это действительно некрасиво, мой новый подход выглядит следующим образом:

// No so smelly code 
public class Model 
{ 
    public void Store(SomeObject someObject) 
    { 
    throw new Expception("Not allowed!"); 
    } 

    public void Store(SpecificObject1 someObject) 
    {} 

    public void Store(SpecificObject2 someObject) 
    {} 

} 

Когда новый тип SomeObject приходит я должен реализовать, как это конкретный объект хранится , это нарушит OCP, потому что мне нужно изменить модельный класс.

Чтобы переместить логику магазина в SomeObject, также чувствуется некорректная причина, тогда я нарушу SRP (?), Потому что в этом случае SomeObject почти как DTO, это не так, как не знать, что хранить.

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

Это потому, что код вызова будет в виде

IEnumerable<SomeObject> sequence; 

Я не знаю конкретных типов объектов последовательности.

Я не могу понять концепцию OCP. У кого-нибудь есть конкретные примеры или ссылки, которые немного больше, чем некоторые примеры Car/Fruit?

+1

Будет намного лучше, если вы сможете показать, что методы Store делают по-другому. – tafa

+0

Неужели было бы так плохо иметь виртуальную функцию 'Store' в' SomeObject'? (http://www.martinfowler.com/bliki/AnemicDomainModel.html) –

+0

Возможно, вы захотите реализовать стратегический паттерн, так как ваш не столь вонючий код нарушает принцип единой ответственности. – Kane

ответ

1

Шаблон Я представляю attemps для регистрации обработчиков для определенных объектов. Должен быть обработчик registerd для каждого типа объекта, который может произойти. Если обработчик не может справиться с этим, генерируется исключение.

Вы можете загружать обработчики (все, что реализует IHandler) динамически из ваших или из других сборок и создавать экземпляры и добавлять их. Итак, достаточно создать класс обработчика для любого типа, который реализует SomeObject.

public interface IHandler { 
    bool TryHandle (SomeObject o); // return true iff handled 
} 

public class Model 
{ 
    private List<SIandler> _Handlers = new List<IHandlers>(); 

    // registers a new handler 
    public void RegisterHandler (IHandler h) { 
     _Handlers.Add(h); 
    } 

    // this tries to store an object by letting all handlers attempts to store 
    public void Store (SomeObject o) { 
     foreach (var h in _Handlers) { 
      if (h.Store(o)) return; 
     } 

     // no handler was able to handle the type 
     throw new Exception(); 
    } 
} 

public class Specific1Handler: IHandler 
{ 
    public bool Handle (SomeObject o) { 
     if (o is SpecificType1) { 
      /* store... */ 
      return true; // we handled this object 
     } else { 
      // we're not qualified 
      return false; 
     } 
    } 
} 

Я считаю, что это соответствовало бы вашим потребностям. (Кстати, я не знаю, имеет ли этот шаблон имя, было бы приятно узнать, есть ли он.)

+0

Это ИМХО, как стратегия и/или цепочка ответственности. –

 Смежные вопросы

  • Нет связанных вопросов^_^