[英]If I can have multiple factory methods in a creator class, why would I ever need the abstract factory pattern?
The abstract factory pattern is useful when we have families of related classes, and we want to instantiate them without relying on the implementation.抽象工厂模式在我们有一系列相关类时很有用,我们希望在不依赖实现的情况下实例化它们。 However, what's wrong with using the factory method pattern in such a situation?
但是,在这种情况下使用工厂方法模式有什么问题呢?
Let's say that we want to construct cross-platform UI elements, eg TextBox
and Button
for Windows and macOS and treat them abstractly.假设我们要构建跨平台的 UI 元素,例如 Windows 和 macOS 的
TextBox
和Button
,并抽象地对待它们。 This is the typical situation in which we use the abstract factory pattern, and we can do so by defining the following:这是我们使用抽象工厂模式的典型情况,我们可以通过定义以下内容来实现:
AbstractUIElementsFactory
interface AbstractUIElementsFactory
接口WindowsUIElementsFactory
implements AbstractUIElementsFactory
WindowsUIElementsFactory
实现AbstractUIElementsFactory
MacUIElementsFactory
implements AbstractUIElementsFactory
MacUIElementsFactory
实现AbstractUIElementsFactory
TextBox
abstract class TextBox
摘要 class
MacTextBox
extends TextBox
MacTextBox
扩展TextBox
WindowsTextBox
extends TextBox
WindowsTextBox
扩展TextBox
Button
abstract class Button
摘要 class
MacButton
extends Button
MacButton
扩展Button
WindowsButton
extends Button
WindowsButton
扩展Button
and the application would decide which concrete factory to create (based on some OS discovery mechanism) and pass it to a UIApplication
class, which instantiates a TextBox
and a Button
, and calls display
on them (which are abstract methods that simply return a String
).并且应用程序将决定创建哪个具体工厂(基于一些操作系统发现机制)并将其传递给
UIApplication
class,它实例化一个TextBox
和一个Button
,并在它们上调用display
(它们是简单返回String
的抽象方法) .
The code for this situation:这种情况的代码:
package abstractFactory;
abstract class Button {
public abstract void display();
}
class MacButton extends Button {
public void display() {
System.out.println("macButton");
}
}
class WindowsButton extends Button {
@Override
public void display() {
System.out.println("winButton");
}
}
abstract class TextBox {
public abstract void display();
}
class MacTextBox extends TextBox {
@Override
public void display() {
System.out.println("macTextBox");
}
}
class WinTextBox extends TextBox {
@Override
public void display() {
System.out.println("winTextBox");
}
}
interface UICreatorAbstractFactory {
Button getButton();
TextBox getTextBox();
}
class MacFactory implements UICreatorAbstractFactory {
@Override
public Button getButton() {
return new MacButton();
}
@Override
public TextBox getTextBox() {
return new MacTextBox();
}
}
class WindowsFactory implements UICreatorAbstractFactory {
@Override
public Button getButton() {
return new WindowsButton();
}
@Override
public TextBox getTextBox() {
return new WinTextBox();
}
}
class UIApplication {
private UICreatorAbstractFactory factory;
UIApplication(UICreatorAbstractFactory _factory) {
factory = _factory;
}
public void displayUI() {
factory.getButton().display();
factory.getTextBox().display();
}
}
public class Main {
public static void main(String[] args) {
new UIApplication(new MacFactory()).displayUI();
}
}
This implementation allows us to get UI elements transparently from factory implementations and also UI elements implementations, which is largely why we would use the pattern.此实现允许我们从工厂实现和 UI 元素实现中透明地获取 UI 元素,这在很大程度上是我们使用该模式的原因。
Using the same TextBox
, Button
, and their derivatives, we can have a factory method implementation with two factory methods in the creator , UICreator
, each of which returns an abstract UI element.使用相同的
TextBox
、 Button
和它们的衍生物,我们可以在creator UICreator
中使用两个工厂方法实现一个工厂方法,每个工厂方法都返回一个抽象的 UI 元素。 And we derive the creator and make two specializations WindowsUICreator
, and MacUICreator
, and each of which returns the appropriate concrete UI element, as follows:我们派生创建者并进行两个特化
WindowsUICreator
和MacUICreator
,每个都返回适当的具体 UI 元素,如下所示:
abstract class UICreator {
public void displayUI() {
getButton().display();
getTextBox().display();
}
protected abstract Button getButton();
protected abstract TextBox getTextBox();
}
class WindowsUICreator extends UICreator {
@Override
protected Button getButton() {
return new WindowsButton();
}
@Override
protected TextBox getTextBox() {
return new WinTextBox();
}
}
class MacUICreator extends UICreator {
@Override
protected Button getButton() {
return new MacButton();
}
@Override
protected TextBox getTextBox() {
return new MacTextBox();
}
}
public class Main {
public static void main(String[] args) {
new MacUICreator().displayUI();
}
}
What are the downsides of this design?这种设计的缺点是什么? I believe it provides the needed decoupling by not having to deal with any concrete classes, and also provides the proper extensibility in the sense that we can introduce new UI elements and give them new factory methods, or newly supported OSs and implement concrete creators for them.
我相信它通过不必处理任何具体类来提供所需的解耦,并且在我们可以引入新的 UI 元素并为它们提供新的工厂方法或新支持的操作系统并为它们实现具体创建者的意义上提供了适当的可扩展性. And if we can use the factory method pattern in the exact situation the abstract factory pattern was designed for, I don't understand why do we have it at all?
如果我们可以在设计抽象工厂模式的确切情况下使用工厂方法模式,我完全不明白我们为什么要拥有它?
I would like to show you an image from Saurav Satpathy's blog here which quickly can explain why you want abstract factory over factory method at times.我想在这里向您展示 Saurav Satpathy 博客中的一张图片,它可以快速解释为什么您有时需要抽象工厂而不是工厂方法。
The argument for dependency injection and collection of related objects makes a lot of sense and here is a coded example by a great creator The Refactoring Guru on Abstract Factory and here is his example on factory method .依赖注入和相关对象收集的论点很有意义,这是伟大的创造者The Refactoring Guru 关于抽象工厂的编码示例,这是他关于工厂方法的示例。 The main difference between the examples in my opinion is the abstract factory better depicts the complexity of factories that create multiple types of objects.
在我看来,这些示例之间的主要区别在于抽象工厂更好地描述了创建多种类型对象的工厂的复杂性。 Additionally, it effectively divides the code in more classes, making each class simpler to understand (but creating more classes in total, of course).
此外,它有效地将代码划分为更多类,使每个 class 更易于理解(当然,总共创建了更多类)。
Keep in mind this is not a very in depth analysis as of now, I want to see other people's opinions on the matter and give it some time to think for myself.请记住,到目前为止,这不是一个非常深入的分析,我想看看其他人对此事的看法,并给我一些时间自己思考。 I may come back in a couple of days with an edit (currently a bit busy, but I sneaked a quick opinion for you)
我可能会在几天后回来进行编辑(目前有点忙,但我偷偷给你一个快速的意见)
Edit #1 Inheritance编辑#1 Inheritance
"Favor object composition over class inheritance. Inheritance breaks encapsulation, implement abstract classes, do not inherit concrete classes! - The Gang of Four on Design Patterns"
“赞成 object 组合超过 class inheritance。Inheritance 打破封装,实现抽象类,不要继承具体类! - 设计模式四人组”
So object inheritance if you read the GoF's book: "Design Patterns Elements of Reusable Object-Oriented Software" is discouraged, especially when systems become more and more complex or higher in scope. Edit influenced by @FelipeLlinares great point indeed.所以 object inheritance 如果你读了 GoF 的书:“可重用面向对象软件的设计模式元素”是不鼓励的,特别是当系统在 scope 中变得越来越复杂或更高时。编辑确实受到@FelipeLlinares 的影响。
They are both about creating new objects but the factory method is used to create one product only while the Abstract Factory is about creating families of related or dependent products.它们都是关于创建新对象,但工厂方法仅用于创建一个产品,而抽象工厂是关于创建相关或依赖产品的系列。 In the Abstract Factory pattern, a class delegates the responsibility of object instantiation to another object via composition, whereas the Factory Method pattern uses inheritance and relies on a subclass to handle the desired object instantiation.
在抽象工厂模式中,class 通过组合将 object 实例化的责任委托给另一个 object,而工厂方法模式使用 inheritance 并依赖子类来处理所需的 object 实例化。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.