Используются ли фабричные методы в Smalltalk, и если да, то как их написать, а не как, например, в Java? Спасибо.
Smalltalk эквивалент фабричного метода?
Ответы (2)
В фабричном шаблоне мы создаем экземпляр некоторого подкласса, не называя его. Рассмотрим фабрику пиццы и иерархию:
Pizza
PepperoniPizza
CheesePizza
...
Мы хотели бы создать экземпляр подкласса пиццы, не зная его имени. Например:
pizza := Pizza flavor: 'cheese' size: 12 inches
отвечает на правильный подкласс пиццы с заполненным размером.
Теперь в Java или C++ можно было бы, вероятно, сделать большой оператор «переключатель» для сравнения разных имен строк. Каждый раз, когда мы добавляли новый подкласс Pizza, нам нужно было помнить о добавлении к главному оператору switch. Типичные примеры см. в статье Википедии.
Не так в Smalltalk, где классы являются объектами первого класса, поэтому мы можем итерировать вниз по иерархии классов, запрашивая соответствие каждого подкласса. Например:
Pizza class>>flavor: aString size: anInteger
matchingClass := self subclasses detect: [:first | first matching: aString].
^matchingClass new size: anInteger.
И всякий раз, когда мы реализуем новый подкласс пиццы, мы реализуем один метод для сопоставления с фабрикой:
CheesePizza class>>matching: aString
^aString = 'cheese'
PepperoniPizza class>>matching: aString
^aString = 'pepperoni'
Нет оператора центрального переключателя, который нужно поддерживать. Просто объекты!
Прежде всего, в Smalltalk у вас есть именованные конструкторы. На самом деле классы — это объекты, а «конструкторы» — это просто методы, определенные в классе, которые возвращают новые экземпляры. Таким образом можно охватить многие случаи использования фабричных методов в других языках.
Например
Thing class >> withName: aString
^ dictionaryOfAllThings
at: aString
ifAbsentPut: (self new name: aString; yourself)
которые получают вещь по имени и создают новую вещь только в том случае, если вещь с таким именем еще не существует.