2009-09-29 2 views
0
interface IDependency 
{ 
    string Baz { get; set; } 
} 

class Foo 
{ 
    IDependency dependency; 

    public Foo(IDependency dependency) 
    { 
     this.dependency = dependency; 
    } 

    public void FubarBaz() 
    { 
     dependency.Baz = "fubar"; 
    } 
} 

Я мог бы также осуществить это как:В чем преимущества неизменяемых объектов над статическими методами?

class FooStatic 
{ 
    public static void FubarBaz(IDependency dependency) 
    { 
     dependency.Baz = "fubar"; 
    } 
} 

Когда я должен выбрать неизменные объекты более статические методы? Есть ли ситуации, когда обратное может быть правдой?

Кроме того, мне кажется, что неизменяемые объекты не должны иметь недействительные методы. Как вы думаете?

+2

Ваш пример вроде нехорошо - у вас есть класс, который является единственной целью в жизни - это изменить какое-то состояние в экземпляре другого класса. Одна хорошая вещь в ООП заключается в том, что классы могут ограничивать сферу действия. – RossFabricant

ответ

3

Неизменяемые объекты, безусловно, могут иметь недействительные методы - существуют другие виды побочных эффектов, помимо изменения состояния объекта. Рассмотрим:

public void WriteTo(Stream stream) 

в качестве примера.

Что касается ваших проблем «неизменяемых объектов и статических методов» - что делать, если ваш метод действительно нуждается в нескольких аспектах состояния Foo? Просто потому, что состояние не изменяется, это не означает, что не имеет смысла инкапсулировать это состояние вместе. Предположим, что у него есть 5 зависимостей вместо одного - вы хотите написать много статических методов, которые принимают 5 параметров? Когда вы получаете шестую зависимость (или даже просто другое состояние), действительно ли вы хотите добавить шестой параметр ко всем методам или просто к конструктору?

+0

Спасибо за ответ; заявляя зависимости, мне кажется, что он достаточно разумен. Однако в ответ на ваш первый абзац не записывает изменение состояния потока в WriteTo? –

+0

@Sam: Да, он изменяет состояние потока - но не состояние объекта, на который вы его вызываете. Поток изменчив, но объект может быть неизменным ... поэтому он по-прежнему является недействительным методом на неизменяемом объекте, не будучи бессмысленным. –

0

FubarBaz() мутирует элемент Foo.dependency поэтому Foo не является неизменным. Неизменность - это конструктивное ограничение, которое может и должно быть лучше выражено в C# путем маркировки полей readonly. Связывание вашей зависимости может и должно выполняться в конструкторе (если вы делаете IoC, большинство фреймворков потребует этого). Неизменная конструкция может в конечном итоге, как это:

class Foo 
{ 
    private readonly IDependency dependency; 

    public Foo(IDependency dependency) 
    { 
     this.dependency = dependency; 
     dependency.Baz = "fubar"; 
    } 
} 

Существует время и место для обоих изменяемых и неизменяемых конструкций класса. Возможно, значение часто меняется, а класс не разделяется, тогда работает изменяемый класс. Преимущество неизменности заключается в том, что он является инвариантным. Вы можете передать ссылку на объект вокруг и быть уверенным, что значение, которое оно указывает, никогда не изменяется. Это мощная концепция, особенно при работе с многопоточными приложениями.

Решение использовать статический класс должно основываться на том, как вы хотите, чтобы вызовы выглядели или вам абсолютно необходимо использовать статику, например, при создании методов расширения. IME, написание вызова перед выполнением вызова - отличный способ принять решение о дизайне перед подключением к реализации. Статика в основном такая же, как и нестатика, за исключением того, что статика не может быть «новой» (построенной вами). Статика не является неизменной, особенно потому, что вы их не строите. У вас только один экземпляр.

Я не вижу причин избегать типов возвращаемых ошибок при использовании методов в неизменном классе.

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