繁体   English   中英

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

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

我试图了解与简单工厂相比何时使用工厂方法模式,我知道每种方法是如何实现的,但我并不清楚。

假设我有提供字符串(汽车名称)的客户端,并且基于该字符串,工厂提供了对象。

我知道方法工厂满足开/关原则,如果我拥有梅赛德斯这样的新汽车品牌,我将不得不编辑开关盒并添加新品牌,这将是一种不好的做法。 但是然后使用Factory方法,因为没有开关箱,我的工厂无法决定要制造哪个对象。 我想我在这里遗漏了一点。 如果我在创建汽车对象时有不同的逻辑/策略,也许应该使用工厂方法,也许是一种制造随机汽车对象的方法/一种采用字符串并根据该字符串制造对象的方法。

如果我在Factory Method getCar()函数中使用并在返回准备使用的对象之前在其中执行更多逻辑,例如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();

    }

}

出于学习目的,最好遵循工厂方法和抽象工厂的GoF定义。 GoF是围绕基本模式的公共参考和讨论。 最好警惕在几个充满广告的网站上找到的许多“示例”,因为某些示例充其量会误导您。

坚持使用GoF有2种工厂模式Factory Method和Abstract Factory。

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

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

示例 :考虑一个TextEditor基类,其中包含C#,PHP,JS,HTML等的子类。每个子类都需要自己的SyntaxChecker对象。 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.

这符合工厂方法的GoF意图。 “定义用于创建对象的接口,但让子类决定实例化哪个类”。

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

抽象工厂抽象工厂的GoF目的是“提供一个用于创建相关或依赖对象族的接口,而无需指定其具体类”。 实际上,这意味着要创建一个抽象的Factory类,其子类定义如何创建相关对象的族。

示例 :扩展TextEditor示例,我们意识到除了SyntaxChecker之外,还需要特定于语言的Formatter和Debug模块。 (我们可以通过Factory Method的多个应用来实现这一点,但这涉及到编辑多个类)。 使用3个抽象方法CreateSyntaxChecker(),CreateDebugger(),CreateFormatter()定义一个抽象Factory类。 然后定义子类PHPFactory,JSFactory,HTMLFactory等,它们各自提供3种方法的实现,并返回正确的对象实例。

考虑以下伪代码的典型用法。

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“标准”,尤其是在学习时。 当您确定自己在做什么时,稍后便可以适应和调整以适应您的需求:-)。

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

仅当可接受紧密耦合时,首选“简单工厂”,因为这种模式会将客户端耦合到工厂实现类。

当需要松散耦合时,通常总是使用Abstract Factory。

如果愿意,可以将开关替换为枚举,并且对所允许枚举列表的简单迭代将返回所需的对象。 我从代码中看到的是,第一个使用委托,第二个将您的客户与具体工厂结合在一起。 我希望这里有第一个。

暂无
暂无

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

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