Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么要使用工厂方法模式而不是简单的工厂_Java_Design Patterns - Fatal编程技术网

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

Java 为什么要使用工厂方法模式而不是简单的工厂,java,design-patterns,Java,Design Patterns,我试图理解什么时候使用工厂方法模式,与简单工厂相比,我知道每个方法模式是如何实现的,但我并不完全理解它的意义 假设我有一个提供字符串(汽车名称)的客户机,工厂根据该字符串提供对象 我知道该方法工厂满足开/关原则,如果我有新的汽车品牌,例如梅赛德斯,我将不得不编辑开关盒并添加新品牌,这将是一个糟糕的做法。但用工厂方法,我的工厂无法决定制造哪个对象,因为没有开关盒。我想我遗漏了一点。如果我在创建汽车对象时有不同的逻辑/策略,也许我应该使用工厂方法,可能是一个生成随机汽车对象的方法,也可能是一个获取字

我试图理解什么时候使用工厂方法模式,与简单工厂相比,我知道每个方法模式是如何实现的,但我并不完全理解它的意义

假设我有一个提供字符串(汽车名称)的客户机,工厂根据该字符串提供对象

我知道该方法工厂满足开/关原则,如果我有新的汽车品牌,例如梅赛德斯,我将不得不编辑开关盒并添加新品牌,这将是一个糟糕的做法。但用工厂方法,我的工厂无法决定制造哪个对象,因为没有开关盒。我想我遗漏了一点。如果我在创建汽车对象时有不同的逻辑/策略,也许我应该使用工厂方法,可能是一个生成随机汽车对象的方法,也可能是一个获取字符串并基于该字符串生成对象的方法

如果我在工厂方法getCar()函数中使用,并在返回ready to use对象之前在那里执行更多的逻辑,比如car.tuneEngine()等,这也是一个好的实践吗

简单工厂

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();     
    }
}
工厂方法模式

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();

    }

}

当首选继承时,工厂方法是首选的,因为该模式是通过继承实现的

只有当紧耦合是可接受的时,简单工厂才是首选,因为该模式将客户机耦合到工厂实现类


当需要松耦合时,最好使用抽象工厂,这几乎总是如此。

如果您愿意,可以用enum替换switch,并且对允许的enum列表进行简单迭代将返回所需的对象。
从代码中我可以看到,第一个是使用委托,第二个是将客户机与混凝土工厂耦合。我更喜欢这里的第一个。

出于学习的目的,遵循GoF对工厂方法和抽象工厂的定义可能是有意义的。GoF是围绕基本模式的公共点参考和讨论。最好提防在几个充斥广告的网站上发现的许多“例子”,因为有些例子充其量只是误导

遵循GoF有两种工厂模式:工厂方法和抽象工厂

简单工厂不是一个单独的模式,它是工厂方法的一个特例。在Gof中没有提到简单工厂模式作为命名模式。见下文

工厂方法:这不涉及工厂对象。顾名思义,它涉及工厂方法()

<强>实例:考虑一个带有C类、PHP、JS、HTML等子类的基本TeXTebug类。每个子类需要自己的SytRealCuffCK对象。TextEditor基类有一个抽象的CreateSyntaxChecker()方法,TextEditor的每个子类实现CreateSyntaxChecker()接口并返回子类所需的特定SyntaxChecker。考虑下面使用的伪代码。

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.
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.
这符合GoF工厂方法的意图。“定义用于创建对象的接口,但让子类决定实例化哪个类”

“简单工厂”:是工厂方法的一种变体。在此变体中,使用文本编辑器示例,TextEditor基类有一个具体的(而不是抽象的)方法CreateSyntaxChecker(),该方法在子类中可能会过度使用,也可能不会过度使用,如果不会过度使用,则使用基类实现

抽象工厂:抽象工厂的GoF意图是“提供一个接口,用于创建相关或从属对象的族,而不指定它们的具体类”。这在实践中意味着创建一个抽象工厂类,其子类定义如何创建相关对象的族

示例:扩展TextEditor示例,我们意识到除了SyntaxChecker之外,还需要特定于语言的格式化程序和调试模块。(我们可以通过工厂方法的多个应用程序来实现这一点,但这需要编辑几个类)。使用3个抽象方法CreateSyntaxChecker()、CreateDebugger()和CreateFormatter()定义一个抽象工厂类。然后定义子类PHPFactory、JSFactory、HTMLFactory等,每个子类都提供3个方法的实现,并返回正确的对象实例

考虑下面的伪代码作为典型用途

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.
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.

我强烈建议您重构代码,以符合GoF“标准”作为起点,尤其是在学习时。以后,当您确信自己在做什么时,您可以自由地进行调整,以适应您的需要:-)。

您的模式可能重复,但您的模式都是错误的-第一个确实是工厂模式,第二个是抽象工厂模式。所谓方法工厂,我假设你指的是静态方法工厂模式——这两者都不是。@BoristheSpider第二个是抽象工厂吗?抽象工厂用于对象族。在他的例子中只有一种类型的对象,那就是汽车。工厂方法模式具有抽象的创建功能,这使大多数人认为它是抽象的工厂模式。所以,他的例子很贴切。