简体   繁体   English

为什么要使用工厂方法模式而不是简单工厂

[英]Why to use Factory method pattern instead of Simple factory

Im trying to understand when to use Factory method pattern compared to Simple factory, I know how each implements but I don't exactly get the point of it. 我试图了解与简单工厂相比何时使用工厂方法模式,我知道每种方法是如何实现的,但我并不清楚。

Let's assume I have client that provides string(name of the car) and based on that string, factory provides object. 假设我有提供字符串(汽车名称)的客户端,并且基于该字符串,工厂提供了对象。

I know that method factory satisfies open/closed principle and if I had new car brand for example Mercedes, I would have to edit switch case and add new brand and that would be bad practice. 我知道方法工厂满足开/关原则,如果我拥有梅赛德斯这样的新汽车品牌,我将不得不编辑开关盒并添加新品牌,这将是一种不好的做法。 But then with Factory method my factory can't decide on which object to make because there is no switch case. 但是然后使用Factory方法,因为没有开关箱,我的工厂无法决定要制造哪个对象。 I guess I'm missing a point here. 我想我在这里遗漏了一点。 Maybe I should use factory method if I had diffrent logic/strategy on creating car object, maybe one that makes random car object and one that takes string and makes object based on that string. 如果我在创建汽车对象时有不同的逻辑/策略,也许应该使用工厂方法,也许是一种制造随机汽车对象的方法/一种采用字符串并根据该字符串制造对象的方法。

Also would It be a good practice if I used in Factory Method getCar() function and do some more logic there, like maybe car.tuneEngine() etc. before returning ready to use object? 如果我在Factory Method getCar()函数中使用并在返回准备使用的对象之前在其中执行更多逻辑,例如car.tuneEngine()等,这将是一个好习惯吗?

Simple factory 简单工厂

public class FordCar extends Car {

    public FordCar() {
        super("Ford", "Mondeo", 1.6);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void move() {
        System.out.println("Ford moves");

    }

}

public class CarFactory {

    public Car getCar(String brand) {
        switch (brand) {
        case "ferrari":
            return new FerrariCar();
        case "ford":
            return new FordCar();
        default:
            return null;

        }
    }
}

public class Client {

    public static void main(String[] args) {

        //Simple factory
        CarFactory carFactory = new CarFactory();
        Car clientSimpleCar = carFactory.getCar("ford");
        clientSimpleCar.move();     
    }
}

Factory method pattern 工厂方法模式

public abstract class CarMethodFactory {

    public Car getCar(){
        Car car = createCar();
        return car;
    }

    public abstract Car createCar();

}

public class FordMethodFactory extends CarMethodFactory{

    @Override
    public Car createCar() {
        return new FordCar();
    }

}

public class Client {

    public static void main(String[] args) {

        CarMethodFactory carMethodFactory = new FordMethodFactory();
        Car clientMethodCar = carMethodFactory.getCar();
        clientMethodCar.move();

    }

}

For learning purposes it might make sense to stay with the GoF definitions of Factory Method and Abstract Factory. 出于学习目的,最好遵循工厂方法和抽象工厂的GoF定义。 GoF is a common point reference and discussion around the basic patterns. GoF是围绕基本模式的公共参考和讨论。 Its best to be wary of many of the "examples" found on several advertisement filled sites because some examples are at best misleading. 最好警惕在几个充满广告的网站上找到的许多“示例”,因为某些示例充其量会误导您。

Sticking with GoF there are 2 factory patterns Factory Method and Abstract Factory. 坚持使用GoF有2种工厂模式Factory Method和Abstract Factory。

Simple Factory is not a separate pattern, it is a special case of Factory Method. 简单工厂不是单独的模式,它是工厂方法的特例。 There is no mention of Simple Factory pattern as a named pattern in Gof. 在Gof中,没有提到将简单工厂模式作为命名模式。 See below. 见下文。

Factory Method : This does NOT involve a Factory object. 工厂方法 :不涉及工厂对象。 It involves Factory methods() as the name suggests. 顾名思义,它涉及Factory Methods()。

Example : Consider a base TextEditor class with subclasses for C#, PHP, JS, HTML etc. Each subclass needs its own SyntaxChecker object. 示例 :考虑一个TextEditor基类,其中包含C#,PHP,JS,HTML等的子类。每个子类都需要自己的SyntaxChecker对象。 The TextEditor base class has an abstract CreateSyntaxChecker() method and each subclass of TextEditor implements CreateSyntaxChecker() interface and returns the specific SyntaxChecker needed by the subclass. TextEditor基类具有抽象的CreateSyntaxChecker()方法,并且TextEditor的每个子类都实现CreateSyntaxChecker()接口,并返回子类所需的特定SyntaxChecker。 Consider pseudo code below for typical use. 考虑以下伪代码的典型用法。

Editor = new PHPTextEditor;  // instantiates PHP subclass of  TextEditor
_syntaxChecker = this->CreateSyntaxChecker();     // The constructor of  
PHPTextEditor invokes its over-ridden CreateSyntaxChecker() method, which returns 
the correct PHP SyntaxChecker object.

This complies with GoF Intent of Factory Method. 这符合工厂方法的GoF意图。 "Define an interface for creating an object, but let subclasses decide which class to instantiate". “定义用于创建对象的接口,但让子类决定实例化哪个类”。

"Simple Factory" : is a variation of Factory Method. “简单工厂” :是工厂方法的一种变体。 In this variation, using the text editor example, the TextEditor base class has an concrete (instead of abstract) method CreateSyntaxChecker(), which may or not be over-ridden in subclasses, and if not over-ridden, the base class implementation is used. 在此变体中,使用文本编辑器示例,TextEditor基类具有一个具体的(而不是抽象的)方法CreateSyntaxChecker(),该方法可以在子类中覆盖,也可以不覆盖,如果不覆盖,则基类实现为用过的。

Abstract Factory : The GoF Intent of Abstract Factory is to "provide an interface for creating families of related or dependent object, without speciifying their concrete classes". 抽象工厂抽象工厂的GoF目的是“提供一个用于创建相关或依赖对象族的接口,而无需指定其具体类”。 What this means in practice is creating an abstract Factory class, whose subclasses define how to create families of related objects. 实际上,这意味着要创建一个抽象的Factory类,其子类定义如何创建相关对象的族。

Example : Extending the TextEditor example, we realise that also need language specific Formatter, and Debug modules in addition to SyntaxChecker. 示例 :扩展TextEditor示例,我们意识到除了SyntaxChecker之外,还需要特定于语言的Formatter和Debug模块。 (We could achieve this by multiple applications of Factory Method, but this involves editing several classes). (我们可以通过Factory Method的多个应用来实现这一点,但这涉及到编辑多个类)。 Define an abstract Factory class with 3 abstract methods CreateSyntaxChecker(), CreateDebugger(), CreateFormatter(). 使用3个抽象方法CreateSyntaxChecker(),CreateDebugger(),CreateFormatter()定义一个抽象Factory类。 Then define subclass PHPFactory, JSFactory, HTMLFactory etc each of which provide implementations for the 3 methods and return the correct object instances. 然后定义子类PHPFactory,JSFactory,HTMLFactory等,它们各自提供3种方法的实现,并返回正确的对象实例。

Consider pseudo code below for typical use. 考虑以下伪代码的典型用法。

Factory = new PHPFactory();
Editor = new PHPEditor(Factory);    // Constructor of PHPEditor will invoke the 3 
Factory methods to instantiate the correct versions of the SyntaxChecker, Debugger 
and Formatter objects.

I strongly suggest refactoring your code to comply with the GoF "standard" as a starting point, especially when learning. 我强烈建议您重构代码以符合GoF“标准”,尤其是在学习时。 Later feel free to adapt and adjust to suit your needs, when you are sure of what you are doing :-). 当您确定自己在做什么时,稍后便可以适应和调整以适应您的需求:-)。

Factory Method is preferred when inheritance is preferred, because that pattern is implemented through inheritance. 当首选继承时,首选工厂方法,因为该模式是通过继承实现的。

Simple Factory is preferred only when tight coupling is acceptable, because that pattern couples the client to the factory implementation class. 仅当可接受紧密耦合时,首选“简单工厂”,因为这种模式会将客户端耦合到工厂实现类。

Abstract Factory is preferred when loose coupling is desired, which is almost always. 当需要松散耦合时,通常总是使用Abstract Factory。

You can replace switch with enum if you like and simple iteration over list of allowed enum will return your desired object. 如果愿意,可以将开关替换为枚举,并且对所允许枚举列表的简单迭代将返回所需的对象。 What i can see from the code is that the first one is using delegation, and the second one couples your client with the concrete factory. 我从代码中看到的是,第一个使用委托,第二个将您的客户与具体工厂结合在一起。 I would prefer the first one here. 我希望这里有第一个。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM