Форум программистов, компьютерный форум, киберфорум
ООП и паттерны
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/4: Рейтинг темы: голосов - 4, средняя оценка - 5.00
1 / 1 / 0
Регистрация: 05.10.2015
Сообщений: 19

Применение "FactoryMethod"

14.10.2015, 23:00. Показов 737. Ответов 11
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Допустим у меня есть:
C#
1
abstract class Paratemeter { здесь неважно что }
А еще есть соответственно наследники:
C#
1
2
sealed class numericalParameter { ... }
sealed class logicalParameter { ... }
А теперь вот, собственно, вопрос:
C#
1
2
3
4
5
6
public Parameter CreateParameter(object value)
{
Parameter output;
логика: если входной тип есть число, тогда ссылке "output" присваивается new numericalParmeter();
в противном случае - понятно что
}
на выходе получаем тип Parameter, но фактически-то там его наследник. а что делать, если у наследника определен фукнционал, которого нет в самом Paramter?
в таком случае
C#
1
2
Paramter @this = CreateParamter(...); 
@this.ВызовМетодаКоторогоНет_у_АбстракногоРодителя не катит.
есть ли какие-то варианты докопаться до функционала кроме:
C#
1
((numericalParameter)@this).ВызовМетодаКоторогоНет_у_АбстракногоРодителя
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
14.10.2015, 23:00
Ответы с готовыми решениями:

Запускается FactoryMethod.Program вместо AbstractFactory.Program - как исправить?
Запускается FactoryMethod.Program вместо AbstractFactory.Program - как исправить?

Применение
Возможно вы посчитаете данный вопрос глупым. Но я его задам. Где можно применять C++ и C программисту, при этом не используя GUI? И...

Применение C#
Привет всем! Работаю сис. админом и мне как то надоело хочу уйти в кодеры, мне очень нравиться язык программирования C# в уневери писал на...

11
1264 / 978 / 384
Регистрация: 02.09.2012
Сообщений: 3,024
14.10.2015, 23:45
Конечно не катит... как компилятор должен догадаться, что вы создадите в CreateParameter??! А там написано, что будет создан Parameter и функционал будет как у абстрактного Parameter.
Либо делать CreateNumericalParameter, либо каст.
0
1 / 1 / 0
Регистрация: 05.10.2015
Сообщений: 19
15.10.2015, 00:36  [ТС]
В данном случае речь идет о применении паттерна. Кстати, я в теме написал "приминении". Так вот. Смысл в том, что как только вы ссылке Paramter (абстрактный класс) присваиваете его наследника, то функционал-то будет задействован наследника (т.е. будет работать тот код, который под меткой override). Это очень удобно работать с более абстрактными уровнями, чем с конкретными реализациями - делает проект в целом гораздо более гибким. Проблема в том, что получается, как я понял, весь функционал лучше определять сразу в абстрактном классе. Иначе придется
C#
1
((приводить к конкретному типу)абстрактный тип).ВызыватьНужныйМетод
0
Модератор
Эксперт функциональных языков программирования
3136 / 2283 / 469
Регистрация: 26.03.2015
Сообщений: 8,885
15.10.2015, 15:22
Цитата Сообщение от 52Hertz Посмотреть сообщение
Paramter @this = CreateParamter(...);
Как это понимать? Что такое "@this"?
На всякий случай замечу, что объект не может создать (или заменить) сам себя.

Добавлено через 9 минут
CreateParameter означает "хочу создать объект с такой-то функциональностью".
Приведение типа означает "на самом деле ожидаю от этого объекта другую функциональность".
Как поступать, зависит от того, что реально требуется (различно в разных случаях).
0
1 / 1 / 0
Регистрация: 05.10.2015
Сообщений: 19
15.10.2015, 16:03  [ТС]
просто "this" - это keyword для компилятора. но вот если вам вдруг захотелось использовать это слово для создания своего типа? тогда
C#
1
int @this = 0;
Абсолютно валидный код. Потом к этой переменной обращаться как если бы у нее было любое другое имя (не-keyword).

В моем же примере @this - это абстрактный параметр (ссылка), которая указывает на наследника абстрактного класса (как известно, создать экземляр абстрактного класса просто запрещено!).
0
306 / 101 / 18
Регистрация: 04.07.2014
Сообщений: 571
15.10.2015, 17:17
52Hertz
Определение абстрактных классов и интерфейсов суть определение типов.

Конечно, с каждым классом неявно связывается тип, которому будут принадлежать все объекты этого класса. Однако класс одновременно с типом определяет и некоторую реализацию. Таким образом, в C# каждая реализация одновременно получает синтаксическую метку, которая будет связана только с этой реализацией. Если ограничиваться только такой системой типов, то ничего не запрограммируешь, так как множество корректных программ катастрофически сужается.

Эта проблема может быть разрешена при помощи инструмента наследования: если класс DerivedClass наследует классу BaseClass, то он вместе с меткой DerivedClass получает метку BaseClass. Такой подход позволяет Вам под одной типовой меткой использовать несколько реализаций!

Проектировать такую систему можно двумя способами.
i) Определить некоторый тип, правила редукции для которого (читай методы) будут определять некоторую абстракцию предметной области. Затем создавать реализации для этой абстракции, наследуя абстрактному классу или интерфейсу.
ii) Сначала определить различные "кирпичики-реализации", а затем провести аудит типов: какие из реализаций подчиняются общим аксиомам и правилам. Для таких реализаций уже определить общий тип, отвечающий некоторой абстракции.

Но нельзя не делать ни того, ни другого. Если у Вас есть совершенно не связанный логически и аксиоматически набор реализаций, то никакого общего абстрактного класса у них быть не может, и не нужно его "придумывать из пальца". Если некоторый интерфейс не определяет никакой абстракции, а просто является технической деталью -- его тоже нужно срочно ликвидировать и провести аудит: кто отвечает на самом деле за реализацию этого технического момента. Если такое происходит, то с большой долей вероятности где-то был нарушен TDA принцип и часть внутреннего устройства какой-то абстракции "выпала" наружу. И чтобы сохранить инкапсуляцию была "выдумана" новая, несуществующая в предметной области абстракция.
0
Эксперт функциональных языков программированияЭксперт Java
 Аватар для korvin_
4575 / 2774 / 491
Регистрация: 28.04.2012
Сообщений: 8,779
16.10.2015, 01:10
Цитата Сообщение от 52Hertz Посмотреть сообщение
на выходе получаем тип Parameter, но фактически-то там его наследник. а что делать, если у наследника определен фукнционал, которого нет в самом Paramter?
Ничего. Тебе не нужно этого делать. Фабрика и интерфейсы для того и нужны, чтобы создавать объекты разных классов в зависимости от входных параметров, реализующих один и тот же тип, т.к., обычно, далее эта фабрика передаётся куда-то ещё и там уже используется.

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

C#
1
public <T> T CreateParameter(object value)
но, насколько я знаю, написать при этом реализации для специфических типов будет невозможно, но я плохо знаком с C#, может, как-то так:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
interface ConvertableFromObject<T> {
  static T Convert(object obj);
}
 
abstract class Paratemeter<T> : ConvertableFromObject<T> { /* здесь неважно что */ }
 
sealed class numericalParameter : Parameter<numericalParameter> {
  public static numericalParameter Convert(object obj) { /* ... */ }
  /* ... */
}
 
sealed class logicalParameter : Parameter<logicalParameter> {
  public static logicalParameter Convert(object obj) { /* ... */ }
  /* ... */
}
 
public <T : ConvertableFromObject> T CreateParameter(object value) {
  return T.Convert(value);
}
А вообще, я бы не стал мудрить и сделал бы примерно так:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
interface Parameter<T> {
  void SetFrom(object obj);
}
 
sealed class numericalParameter : Parameter<int> {
  public void SetFrom(object obj) { /* ... */ }
  /* ... */
}
 
sealed class logicalParameter : Parameter<bool> {
  public void SetFrom(object obj) { /* ... */ }
  /* ... */
}
т.к., раз ты пытаешься использовать конкретные классы, то ты их можешь создавать статично с помощью банального new.
0
Модератор
Эксперт функциональных языков программирования
3136 / 2283 / 469
Регистрация: 26.03.2015
Сообщений: 8,885
16.10.2015, 12:23
Вариантов много. Выбор варианта зависит от того, что нужно в каждом конкретном случае.

По описанию проблемы, которое дал нам ТС, я вообще не понимаю суть вопроса (при чём здесь шаблон FactoryMethod).
Paramter @this = ...
У нас объект типа Parameter. Очевидно, что если мы хотим вызвать метод другого класса, мы сначала должны привести к соответствующему типа. Это никак не связано с тем, как именно мы создали объект.

Мы не можем использовать здесь переменную типа numericalParameter, потому что это вызывало бы исключение, когда CreateParameter() возвращает объекты других классов (например, logicalParameter).
Если мы точно знаем, что здесь не может создаваться объект другого класса, то зачем мы используем CreateParameter()? Почему не используем метод, который возвращает numericalParameter?
0
1 / 1 / 0
Регистрация: 05.10.2015
Сообщений: 19
16.10.2015, 14:02  [ТС]
На самом деле вопрос был именно при применение "фактори метод". Я просто только начал разбираться с этим шаблоном и кое-где пытаюсь его использовать. По той схеме, на которую я наткнулся, логика именно такая, как я привел в первом посте этой темы.
0
Модератор
Эксперт функциональных языков программирования
3136 / 2283 / 469
Регистрация: 26.03.2015
Сообщений: 8,885
16.10.2015, 15:30
Суть этого шаблона в том, что метод может создать и вернуть объект любого типа, пронаследованного от данного базового. А значит мы не можем (без дополнительных проверок) использовать методы, которых нет у данного базового (в C# и других языках со статической типизацией). И это не ограничение шаблона, а просто мы не знаем, есть ли данный метод у данного объекта.
0
1 / 1 / 0
Регистрация: 05.10.2015
Сообщений: 19
16.10.2015, 20:55  [ТС]
ребята, кому интересно, я вот нарыл очень интересную разновидность этого паттерна, основанного на рефлексии.
C#
1
2
3
4
5
public object Create(string className, ...)
{
Type instanceType = Type.GetType(className); // полное название namespace.className
Activator.CreateInstance(instanceType); 
}
...там в активаторе еще какие-то параметры есть, не суть.
таким же способом можно и поля/свойства инициализировать. через GetProperty, например.
0
306 / 101 / 18
Регистрация: 04.07.2014
Сообщений: 571
17.10.2015, 15:46
Цитата Сообщение от 52Hertz Посмотреть сообщение
интересную разновидность этого паттерна, основанного на рефлексии
Это не вариант паттерна. Это заплатка на коде, которая зашила дыру в проекте, который никаких паттернов не использовал.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
17.10.2015, 15:46
Помогаю со студенческими работами здесь

применение c++
в 1 семестре начали проходить с++ за сем дошли до указателей (во 2 их начнем) прошли: типы, константы, операции, функции (передача по...

Применение цикла For
Дано вещественное число A и натуральное число N. Используя один цикл, найти сумму -1 + A - A^2 + A^3 - .... + (-1)^N+1 * A^n

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

Применение на практике
Мне интересно, а будет ли работать приложение, откомпилированное в PascalABC.net у &quot;типичного пользователя Windows&quot;? То есть, не...

Применение запроса
&amp;НаСервере Процедура СоставСотрудникПриИзмененииНаСервере() Запрос = Новый Запрос( &quot;ВЫБРАТЬ ПЕРВЫЕ 1 |Должность ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru