Реализует ли ChannelFactory фабричный шаблон?

Я начал изучать WCF и уже совсем запутался. Я немного почитал о фабричном шаблоне и не могу понять, как и почему ChannelFactory<> его реализует.

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

ChannelFactory<IRequestChannel> factory = new 
                    ChannelFactory<IRequestChannel>(binding, address);
IRequestChannel channel = factory.CreateChannel();

Следующий код не является допустимым, но он просто используется для демонстрации того, что, насколько я могу судить, ChannelFactory не дает никаких преимуществ по сравнению с прямым созданием экземпляра определенного класса канала:

IRequestChannel channel=new RequestChannelClass(binding, address);

а) Единственным преимуществом первого примера (реализация фабричного шаблона) является то, что клиентский код не нужно изменять в случае, если тип объекта, возвращаемый factory.CreateChannel, изменится когда-нибудь в будущем.

Но если это причина реализации фабричного шаблона, то любой метод, возвращающий объект, должен реализовывать фабричный шаблон, просто на случай, если тип возвращаемого объекта когда-либо изменится в будущем?!

c) Таким образом, если бы ChannelFactory<>.CreateChannel действительно реализовал фабричный шаблон, то клиентский код мог бы сообщить factory.GetFactory (скажем, через параметр), какого типа должен быть объект/продукт, возвращаемый factory.CreateFactory?!

г) Точно так же, насколько я могу судить, класс ChannelFactory также не реализует фабричный шаблон?

благодарю вас

ОТВЕТ Джастину Нисснеру:

б) Шаблон Factory не обязательно требует, чтобы вы могли указать конкретный тип, который будет создан. Это также позволяет фабрике определять конкретный тип на основе переданных ей параметров (в данном случае привязки и адреса).

Итак, ChannelFactory.CreateChannel выбрать конкретный тип для возврата на основе значений привязки и адреса? Я думал, что он всегда возвращает один и тот же конкретный тип, независимо от адреса и значений привязки?!

Как я уже спрашивал двух других авторов, согласны ли вы с тем, что если бы ChannelFactory.CreateChannel всегда возвращал экземпляр одного и того же конкретного типа, независимо от значений привязки и адреса, то ChannelFactory не реализовывал бы фабричный шаблон?


ОТВЕТ Кевину Нельсону

А) Есть 2 преимущества. 1) код реализации не должен меняться, если вы начнете использовать новую реализацию IRequestChannel.

Верно, но, как я упоминал другим авторам, если это единственное требование к классу, который должен быть квалифицирован как класс, реализующий фабричный шаблон, то любой класс с методом (с типом интерфейса в качестве возвращаемого типа), который создает и возвращает конкретный экземпляр, реализует фабричный шаблон? Насколько я могу судить, фабричный шаблон — это когда фабрика производит разные продукты на основе значений, каким-то образом предоставленных клиентским кодом?!

С другой стороны, если я правильно понял Стива Эллинджера, то на основе значений привязки и адреса (переданных конструктору ChannelFactory) вызов ChannelFactory.CreateChannel выберет конкретный тип для возврата на основе значений привязки и адреса (предоставленных конструктору). Если это так, то я могу понять, почему мы говорим, что ChannelFactory реализует фабричный шаблон?!

Согласитесь ли вы с тем, что если бы ChannelFactory.CreateChannel всегда возвращал экземпляр одного и того же конкретного типа, независимо от значений привязки и адреса, то ChannelFactory не реализовывал бы фабричный шаблон?


ОТВЕТ Стиву Эллингеру

IRequestChannel реализуется абстрактным классом RequestChannel. В .Net 4.0 HttpChannelFactory.HttpRequestChannel, ReliableRequestSessionChannel и StreamedFramingRequestChannel наследуются от RequestChannel. Так:

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

Но тогда мы могли бы утверждать, что любой класс с методом (с типом интерфейса в качестве возвращаемого типа), который создает и возвращает конкретный экземпляр, реализует фабричный шаблон?

c) Клиентский код сообщает фабрике, что следует вернуть, косвенно посредством переданной привязки и адреса.

Я думал, что ChannelFactory.CreateChannel всегда будет возвращать экземпляр одного и того же конкретного типа, независимо от привязки и адреса, переданных конструктору ChannelFactory. Но вы говорите, что на основе значений привязки и адреса (переданных конструктору ChannelFactory) вызов ChannelFactory.CreateChannel вернет один из следующих типов: HttpChannelFactory.HttpRequestChannel ,ReliableRequestSessionChannel and StreamedFramingRequestChannel?

Если это так, то я могу понять, почему мы говорим, что ChannelFactory реализует фабричный шаблон?!

Согласитесь ли вы с тем, что если бы ChannelFactory.CreateChannel всегда возвращал экземпляр одного и того же конкретного типа, независимо от значений привязки и адреса, то ChannelFactory не реализовывал бы фабричный шаблон?

ВТОРОЙ ОТВЕТ Стиву Эллингеру

а) Таким образом, в зависимости от значений привязки и адреса ChannelFactory.CreateChannel возвращает HttpRequestChannel, ReliableRequestSessionChannel или StreamedFramingRequestChannel? Или он также может возвращать некоторые другие типы?

б) если клиентский код всегда будет использовать экземпляр канала одного и того же типа (скажем, HttpRequestChannel ), то нет ничего плохого, если вместо использования ChannelFactory.CreateChannel мы напрямую создадим экземпляр HttpRequestChannel:

 HttpRequestChannel channel = new HttpRequestChannel( ... )  

c) Кстати, есть идеи, почему msdn не содержит записей, описывающих классы HttpRequestChannel, ReliableRequestSessionChannel и StreamedFramingRequestChannel?


person user437291    schedule 25.10.2010    source источник


Ответы (3)


IRequestChannel реализуется абстрактным классом RequestChannel. В .Net 4.0 HttpChannelFactory.HttpRequestChannel, ReliableRequestSessionChannel и StreamedFramingRequestChannel наследуются от RequestChannel. Так:

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

c) Клиентский код сообщает фабрике, что следует вернуть, косвенно посредством переданной привязки и адреса. Я, например, не хотел бы проходить весь свой код, чтобы изменить конкретный тип, потому что Microsoft решила устареть тот, который я использовал.

г) Да, учитывая структуру, упомянутую в начале, это типичная реализация фабричного шаблона.

Редактировать:

заводской образец?

Но тогда мы могли бы утверждать, что любой класс с методом (с типом интерфейса в качестве возвращаемого типа), который создает и возвращает конкретный экземпляр, реализует фабричный шаблон?

Не обязательно, если цитировать книгу «Шаблоны проектирования»: шаблон абстрактной фабрики предоставляет интерфейс для создания семейств связанных или зависимых объектов без указания их конкретных классов.

Итак, согласитесь ли вы с тем, что если бы ChannelFactory.CreateChannel всегда возвращал экземпляр одного и того же конкретного типа, независимо от значений привязки и адреса, то в ChannelFactory не было бы реализованного фабричного шаблона?

Да

Редактировать2:

а) Он может возвращать другие типы, поскольку в WCF можно создавать собственные привязки.

б) и в) HttpChannelFactory.HttpRequestChannel — защищенный класс, ReliableRequestSessionChannel и StreamedFramingRequestChannel — внутренние классы; вот почему вы не можете найти их в msdn, а также почему вы не можете напрямую создавать экземпляры этих классов. Я узнал о них через Reflector, я хочу упомянуть о них, что ChannelFactory не обязательно все время возвращает один и тот же конкретный тип.

person Steve Ellinger    schedule 25.10.2010
comment
Я не буду приставать к вам после этого, но не могли бы вы увидеть мою вторую правку? - person user437291; 26.10.2010

Шаблон Factory используется для возврата конкретной реализации более общего класса/интерфейса.

В этом случае ChannelFactory возвращает конкретную реализацию IRequestChannel. Нигде в вашем коде вы не сообщаете фабрике, какой конкретный класс нужно вернуть, что делает это фабрикой. Что касается ваших баллов:

а) Часто считается хорошей практикой кодирования возвращать наименее конкретный возможный тип. Если вы можете обойтись без возврата экземпляра интерфейса, сделайте это. Это уменьшит головную боль при обслуживании в будущем.

Имейте в виду, однако, что возврат наименее специфичного типа не имеет ничего общего с шаблоном Factory. Шаблон Factory предназначен для создания экземпляра объекта.

б) Шаблон Factory не обязательно требует, чтобы вы могли указать конкретный тип, который будет создан. Это также позволяет фабрике определять конкретный тип на основе переданных ей параметров (в данном случае binding и address).

c) Да, ChannelFactory реализует шаблон Factory.

person Justin Niessner    schedule 25.10.2010

Есть другие, которые, вероятно, более эффективны с шаблонами (и их объяснением), чем я, но вот:

А) Есть 2 преимущества. 1) код реализации не должен меняться, если вы начнете использовать новую реализацию IRequestChannel. 2) Это также позволяет вам создавать фиктивные объекты. В своем проекте модульного тестирования вы указываете ChannelFactory создать экземпляр Mock IRequestChannel. Таким образом, вы можете сосредоточить свой модульный тест только на специфике тестируемого метода, а не создавать гигантский тест, который создает реальные экземпляры всего и т. д. (Если вы незнакомы, посмотрите Test Driven Development (TDD). ), инверсия управления (IoC) и внедрение зависимостей (в основном подмножество IoC).

Б) Я бы сказал, что вы обычно хотите использовать фабричный шаблон между слоями, а не внутри слоев. Например. ваш сервисный уровень будет реализовывать фабрику для ваших классов уровня репозитория. Таким образом, если ваш ICustomerRepostory изменится с NHibernateCustomerRepository на CouchDBCustomerRespository... ваш сервисный уровень не должен ничего знать об этом изменении.

Другой постер ответил на другие вопросы, я думаю... так что я оставлю C&D в покое.

ОТВЕТ ИЗМЕНИТЬ:

Согласитесь ли вы с тем, что если бы ChannelFactory.CreateChannel всегда возвращал экземпляр одного и того же конкретного типа, независимо от значений привязки и адреса, то в ChannelFactory не было бы реализованного фабричного шаблона?

Извините, возможно, я не понимаю его семантики... но, насколько я понимаю, дело не столько в том, возвращает ли он более одного конкретного класса, сколько в его способности возвращать другой конкретный класс, если это необходимо возникает. Если он не может производить разные конкретные классы, то это не будет фабрикой... но если он "может" производить разные конкретные классы, если и когда возникнет необходимость, то это фабричный шаблон. Кроме того, мне придется заявить о своем невежестве... и даже в этом я не утверждаю, что не могу ошибаться.

person Kevin Nelson    schedule 25.10.2010
comment
Кстати, если клиентский код всегда будет использовать экземпляр канала одного и того же типа (скажем, HttpRequestChannel ), то нет ничего плохого, если вместо использования ChannelFactory.CreateChannel мы напрямую создадим экземпляр HttpRequestChannel => канал HttpRequestChannel = new HttpRequestChannel(...)? - person user437291; 26.10.2010
comment
ИМХО - если вы ЗНАЕТЕ, что вам никогда не понадобится менять конкретный класс, использование фабричного шаблона добавляет лишние накладные расходы. Я видел, как фабричный шаблон использовался чрезмерно и неправильно до такой степени, что он только усложнял работу без всякой причины. - person Kevin Nelson; 26.10.2010