简体   繁体   English

如果我可以在创建者 class 中拥有多个工厂方法,为什么我还需要抽象工厂模式?

[英]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 的TextBoxButton ,并抽象地对待它们。 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.使用相同的TextBoxButton和它们的衍生物,我们可以在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:我们派生创建者并进行两个特化WindowsUICreatorMacUICreator ,每个都返回适当的具体 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.

相关问题 如果我在实现工厂模式时使用抽象类而不是接口。 它仍然是工厂模式吗? - If I use abstract class instead of interface while implementing factory pattern. Would it still be a factory pattern? 抽象工厂模式与2工厂方法 - Abstract Factory pattern with 2 factory methods “工厂”设计模式在工厂中可以有 1 个以上的抽象类型吗? - Can a 'Factory' Design Pattern have more than 1 abstract type in a factory? 如果我有两个不扩展到抽象父工厂的独立“工厂”,它仍然是工厂模式吗? - If I have two separate "factories" that doesn't extend to an abstract parent factory, is it still a factory pattern? 以下设计模式如何成为工厂方法。 我相信它更像是一个抽象工厂而不是工厂方法 - How is the following design pattern a Factory method. I believe it is more of a Abstract Factory than factory method 没有抽象方法的工厂方法模式是否可能? - Is Factory Method pattern without abstract methods possible? 为什么需要基本抽象工厂抽象工厂模式? - Why base abstract factory is needed Abstract factory pattern? 工厂设计模式-我应该使用哪个类来创建工厂 - Factory Design Pattern - Which class should I use to create a Factory 有没有时间你需要一个没有任何抽象方法的抽象类 - is there a time you would ever need an abstract class without any abstract methods 抽象工厂模式接口实现或类扩展 - Abstract factory pattern interface implementation or class extentsion
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM