Поймите различия в мотивациях:
Предположим, вы создаете инструмент, в котором есть объекты, и конкретную реализацию взаимосвязей объектов.Поскольку вы предвидите изменения в объектах, вы создали косвенное направление, возложив ответственность за создание вариантов объектов на другой объект ( мы называем это абстрактной фабрикой ).Эта абстракция находит сильное преимущество, так как вы предвидите будущие расширения, которым нужны варианты этих объектов.
Еще одна довольно интригующая мотивация в этой линии мыслей - это случай, когда у каждого из объектов всей группы будет соответствующий вариант.Исходя из некоторых условий, будет использоваться любой из вариантов, и в каждом случае все объекты должны быть одного варианта.Это может быть немного противоречивым для понимания, поскольку мы часто склонны думать, что - пока варианты объекта следуют общему унифицированному контракту ( интерфейс в более широком смысле ), конкретный код реализации никогда не должен нарушаться.Интересным фактом здесь является то, что не всегда это верно, особенно когда ожидаемое поведение не может быть смоделировано программным контрактом.
Простым ( заимствованием идеи от GoF ) является любое приложение с графическим интерфейсом, скажем, виртуальный монитор, имитирующий внешний вид ОС MS, Mac или Fedora.Здесь, например, когда все объекты виджета, такие как окно, кнопка и т. Д., Имеют вариант MS, за исключением полосы прокрутки, которая получена из варианта MAC, назначение инструмента не удается.
Эти вышеупомянутые случаи формируют фундаментальную потребность Абстрактная модель фабрики .
С другой стороны, представьте, что вы пишете фреймворк, чтобы многие люди могли создавать различные инструменты (, например, как в приведенных выше примерах ), используя ваш фреймворк.По самой идее фреймворка вам не нужно, хотя вы не можете использовать конкретные объекты в своей логике.Вы скорее заключаете какие-то контракты высокого уровня между различными объектами и тем, как они взаимодействуют.Пока вы ( как разработчик фреймворка ) остаетесь на очень абстрактном уровне, каждый создатель инструмента вынужден следовать вашим фреймворк-конструкциям.Тем не менее, они ( строители инструментов ) имеют свободу выбора, какой объект будет построен и как все объекты, которые они создают, будут взаимодействовать.В отличие от предыдущего случая ( для Abstract Factory Pattern ), вам ( как создателю фреймворка ) в этом случае не нужно работать с конкретными объектами;и скорее может остаться на уровне контракта объектов.Кроме того, в отличие от второй части предыдущих мотиваций, у вас или у создателей инструментов никогда не бывает ситуаций смешивания объектов из вариантов.Здесь, пока код фреймворка остается на уровне контракта, каждый производитель инструментов ограничен ( по природе самого случая ) использованием своих собственных объектов.Создание объектов в этом случае делегируется каждому реализатору, а поставщики фреймворка просто предоставляют единые методы для создания и возврата объектов.Такие методы неизбежны для разработчика инфраструктуры для продолжения работы со своим кодом и имеют специальное имя, называемое Factory method ( Factory Method Pattern для базового шаблона ).
Несколько замечаний:
- Если вы знакомы с «шаблоном метода», то увидите, что фабричные методычасто вызывается из шаблонных методов в случае программ, относящихся к любой форме фреймворка.Напротив, шаблонные методы прикладных программ часто являются простой реализацией определенного алгоритма и лишены фабричных методов.
- Кроме того, для полноты мыслей, используя каркас ( упомянутый выше ), когда создатель инструмента строит инструмент, внутри каждого метода фабрики вместо создания конкретного объекта он / она может дополнительно делегировать ответственность объекту абстрактной фабрики, при условии, что создатель инструмента предвидит изменения конкретных объектовдля будущих расширений.
Образец треские:
//Part of framework-code
BoardGame {
Board createBoard() //factory method. Default implementation can be provided as well
Piece createPiece() //factory method
startGame(){ //template method
Board borad = createBoard()
Piece piece = createPiece()
initState(board, piece)
}
}
//Part of Tool-builder code
Ludo inherits BoardGame {
Board createBoard(){ //overriding of factory method
//Option A: return new LudoBoard() //Lodu knows object creation
//Option B: return LudoFactory.createBoard() //Lodu asks AbstractFacory
}
….
}
//Part of Tool-builder code
Chess inherits BoardGame {
Board createBoard(){ //overriding of factory method
//return a Chess board
}
….
}