2013-06-17 6 views
3

Мне нужна схема:Интерфейс, который содержит способ создания экземпляра

Я использую C#.

Скажите, что есть три актера; Джим, Пэт и Салли. Работа Пэт заключается в создании интерфейса в качестве контракта между Джимом и Салли. Задача Салли - создать класс, который реализует интерфейс, а работа Джима - написать класс, который потребляет объект Салли.

Джим не должен знать о конкретном объекте Салли, только он реализует общий интерфейс.

Пат должен включить в контракт способ Джима создать экземпляр конкретного объекта Салли, но называться интерфейсом.

Там нет никакого способа, чтобы включить статическое определение метода в любом интерфейсе или абстрактного класса, так что вы не можете сделать что-то вроде:

public interface IFoo 
{ 
    public static IFoo CreateIFoo(); 
} 

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

+2

Заводской шаблон, вероятно, поможет здесь. Либо это, либо вам придется переместить статический метод в статический вспомогательный класс вместо этого, но это никоим образом не будет «принудительно» по контракту. –

+0

Спасибо «Поверь мне», Вы указываете мою дилемму, нет способа принудительного использования фабрики как статического метода в классе-помощнике. – dtaylor

ответ

0

Похоже, вам нужна абстрактная фабрика. В дополнение к IFoo, создайте интерфейс IFooFactory с помощью метода CreateFoo. Дайте Jim экземпляр объекта, который реализует IFooFactory, и Джим будет называть метод CreateFoo. Для создания экземпляра объекта, который реализует , может быть либо Sally, либо Pat.

+0

Спасибо Майкл, Так как я понимаю, будет дополнительный интерфейс, такой как: общедоступный интерфейс IFooFactory { общественного IFoo CreateFoo(); } Разве это не вытесняет проблему на заводе? Как Джим получает конкретный объект IFooFactory, создаваемый Салли? – dtaylor

+0

@dtaylor Sally имеет * некоторый * вид 'FooFactory' - фабрику, которая реализует' IFooFactory', которая связана контрактом для создания интерфейсов 'IFoo'. Вы можете создать завод на месте или ввести завод по производству бетона, главное здесь: если Джим хочет от «Сало» «IFoo», он может получить его, вызвав «IFooFactory.Create()». –

1

Если возможно, попросите экземпляр Салли:

class Jim 
{ 
    public Jim(Sally sally){ /* ... */ } 
} 

Если, однако, Джим должен знать, КОГДА построить Салли, вы можете передать в качестве делегата:

class Jim 
{ 
    private Func<Sally> _createSally. 

    public Jim(Func<Sally> createSally) 
    { 
     _createSally = createSally; 
    } 

    public void ConsumeSally() 
    { 
     Sally sally = _createSally(); 
     /* ... */ 
    } 
} 

Простейшее использования :

var jim = new Jim(() => new Sally()); 

Вам не нужен класс (Pat), чтобы знать, как экземпляр вылазку, если это на самом деле не добавляет ценность для вас r код. В любом случае, вы, вероятно, не хотите, чтобы Джим знал о Пэт, поэтому, если Пэт понадобится, то это то, что вам нужно:

var jim = new Jim(() => Pat.GetSally()); 
+0

Спасибо Andre, Боюсь, я немного смущен вашими условиями. Предполагая, что вы имеете в виду, что «Джим» - это класс, который написал Джим, а «Салли» - это класс, который Салли написал, который реализует IFoo, тогда «Джим» не знает о классе «Салли», а только интерфейс IFoo. и «Джим» не может создать «Салли» напрямую. Кроме того, если вы имеете в виду, что «Pat» - это интерфейс IFoo, вы не можете создавать «Pat» для вызова GetSally(). Нет класса «Пэт». – dtaylor

+0

Я говорю, что класс не должен знать, как построить его зависимость, и это включает в себя не знание фабрики (класс Пата). Если Jim (класс, который потребляет зависимость) знает о Pat's (фабрика), у вас будет Service Locator, который считается анти-шаблоном. – Andre

+0

Если класс действительно должен знать, когда строить его зависимость (хотя это не так), оберните его в делегат или в Lazy (только для C# 4+). – Andre

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