плюсы и минусы использования фабрики против обычного конструктора - PullRequest
9 голосов
/ 16 января 2012

(Использование Python 3.2, хотя я сомневаюсь, что это имеет значение.)

У меня есть class Data, class Rules и класс Result.Я использую строчные буквы для обозначения экземпляра класса.

A rules объект содержит правила, которые при применении к объекту data могут создавать объект result.

IЯ решаю, куда поместить (довольно сложный и развивающийся) код, который фактически применяет правила к данным.Я вижу два варианта:

  1. Поместите этот код в метод класса Result, скажем parse_rules.Конструктор Result будет принимать в качестве аргумента объект rules и передавать его на self.parse_rules.

  2. Поместить этот код в новый класс ResultFactory.ResultFactory будет одноэлементным классом, у которого есть метод, скажем, build_result, который принимает rules в качестве аргумента и возвращает недавно построенный result объект.

Чтоплюсы и минусы двух подходов?

Ответы [ 5 ]

3 голосов
/ 16 января 2012

Принципы GRASP содержат рекомендации по распределению ответственности за классы и объекты в объектно-ориентированном проектировании.Например, шаблон Creator предлагает: В общем случае класс B должен отвечать за создание экземпляров класса A, если применяется одно или, предпочтительно, несколько из следующих элементов:

  • Экземпляры B содержат или составно агрегируют экземпляры A
  • Экземпляры B регистрируют экземпляры A
  • Экземпляры B тесно используют экземпляры A
  • Экземпляры B имеют информацию инициализациидля экземпляров A и передать его при создании.

В вашем примере у вас есть сложный и развивающийся код для применения правил к данным.Это предполагает использование Factory Pattern .

Ввод кода в Results противопоказан, потому что 1) результаты не создают результаты, и 2) результаты не являются информационным экспертом (т.е. они не обладают большей частью необходимых знаний).

Короче говоря, ResultFactory кажется разумным местом для концентрации знаний о том, как подать заявку правила до данные для генерации результатов .Если бы вы попытались внедрить всю эту логику в конструкторы классов для Результатов или Правил, это привело бы к сильной связи и потере сцепления.

2 голосов
/ 16 января 2012

Третий сценарий:

Вы можете рассмотреть третий сценарий:

  • Поместите код внутри метода Rules.__call__.
    Insttiating Result как: result = rules(data)

Плюсы:

  • Result s могут совершенно не знать о Rules, который их генерирует (и, возможно, даже об оригинальном Data).
  • Каждый подкласс Rules может настроить создание Result.
  • Это кажется естественным (для меня): Rules применяется к Data доходность Result.
  • И на вашей стороне будет пара принципов GRASP:
    • Создатель : Экземпляры Rules имеют информацию инициализации для экземпляров Result и передают ее при создании.
    • Информационный эксперт : Информационный эксперт приведет к возложению ответственности на класс с наибольшим количеством информации, необходимой для его выполнения.

Побочные эффекты:

  • Муфта : Вы поднимите муфту между Rules и Data:
    • Вам необходимо передать набор данных целом каждому Rules
    • Это означает, что каждый Rules должен иметь возможность выбирать, к каким данным он будет применяться.
1 голос
/ 16 января 2012

Можете ли вы сделать ResultFactory чистой функцией?Бесполезно создавать одноэлементный объект, если все, что вам нужно, это функция.

1 голос
/ 16 января 2012

Почему бы не поставить правила в свои классы?Если вы создаете класс RuleBase, то каждое правило может быть его производным.Таким образом, полиморфизм может быть использован, когда Data требует применения правил.Данные не должны знать или заботиться о том, какие экземпляры Правил были применены (если только сами Данные не являются теми, кто знает, какие правила должны применяться).

Когда необходимо вызывать правила, экземпляр данных может использовать все RuleBase.ExecuteRules () и передать себя в качестве аргумента.Правильный подкласс правила может быть выбран непосредственно из данных, если данные знают, какое правило необходимо.Или можно использовать какой-то другой шаблон проектирования, например, Chain of Responsibility, где Data вызывает шаблон и позволяет вернуть результат.

Это было бы отличным обсуждением на доске.

0 голосов
/ 16 января 2012

Ну, второе совершенно глупо, особенно при всей однотонности.Если Result требует Rules для создания экземпляра, и вы не можете создать его без него, он должен принять это в качестве аргумента __init__.Покупка по шаблону не требуется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...