什么时候在对象中使用工厂方法而不是factory类是一个好主意?


当前回答

这真的是个品味问题。工厂类可以根据需要进行抽象/接口,而工厂方法是轻量级的(而且往往是可测试的,因为它们没有定义的类型,但它们需要一个众所周知的注册点,类似于服务定位器,但用于定位工厂方法)。

其他回答

考虑一个场景,当您必须设计Order和Customer类时。为了简单和初始需求,您不需要Order类的factory,并使用许多“new Order()”语句填充应用程序。一切都很顺利。

现在出现了一个新的需求,即Order对象不能在没有客户关联的情况下实例化(新的依赖项)。现在你有以下考虑。

1-你创建了只对新实现有效的构造函数重载。(不可接受)。 2-您更改Order()签名并更改每个调用。(这不是一个很好的练习,而且真的很痛苦)。

相反,如果你已经为Order Class创建了一个工厂,你只需要修改一行代码就可以了。我建议几乎所有聚合关联都使用Factory类。希望这能有所帮助。

在对象中使用工厂方法是个好主意:

对象的类不知道它必须创建什么确切的子类 Object的类被设计成它创建的对象由子类指定 对象的类将其职责委托给辅助子类,并且不知道确切的类将承担这些职责

在以下情况下使用抽象工厂类是个好主意:

对象不应该依赖于其内部对象是如何创建和设计的 一组链接的对象应该一起使用,您需要满足这个约束 对象应该由几个可能的链接对象家族中的一个来配置,这些对象将成为父对象的一部分 它需要共享只显示接口而不显示实现的子对象

我把工厂比作图书馆的概念。例如,您可以有一个库用于处理数字,另一个库用于处理形状。您可以将这些库的函数存储在逻辑上命名为Numbers或Shapes的目录中。这些是泛型类型,可以包括整数,浮点数,双元,长或矩形,圆形,三角形,在形状的情况下,五边形。

该系统采用了多态、依赖注入和控制反转等技术。

Factory Patterns的目的是:定义一个用于创建对象的接口,但是让子类来决定实例化哪个类。工厂方法允许类延迟实例化到子类。

假设你正在构建一个操作系统或框架,你正在构建所有的离散组件。

下面是PHP中工厂模式概念的一个简单示例。我可能不会完全理解,但这只是一个简单的例子。我不是专家。

class NumbersFactory {
    public static function makeNumber( $type, $number ) {
        $numObject = null;
        $number = null;

        switch( $type ) {
            case 'float':
                $numObject = new Float( $number );
                break;
            case 'integer':
                $numObject = new Integer( $number );
                break;
            case 'short':
                $numObject = new Short( $number );
                break;
            case 'double':
                $numObject = new Double( $number );
                break;
            case 'long':
                $numObject = new Long( $number );
                break;
            default:
                $numObject = new Integer( $number );
                break;
        }

        return $numObject;
    }
}

/* Numbers interface */
abstract class Number {
    protected $number;

    public function __construct( $number ) {
        $this->number = $number;
    }

    abstract public function add();
    abstract public function subtract();
    abstract public function multiply();
    abstract public function divide();
}
/* Float Implementation */
class Float extends Number {
    public function add() {
        // implementation goes here
    }

    public function subtract() {
        // implementation goes here
    }

    public function multiply() {
        // implementation goes here
    }

    public function divide() {
        // implementation goes here
    }
}
/* Integer Implementation */
class Integer extends Number {
    public function add() {
        // implementation goes here
    }

    public function subtract() {
        // implementation goes here
    }

    public function multiply() {
        // implementation goes here
    }

    public function divide() {
        // implementation goes here
    }
}
/* Short Implementation */
class Short extends Number {
    public function add() {
        // implementation goes here
    }

    public function subtract() {
        // implementation goes here
    }

    public function multiply() {
        // implementation goes here
    }

    public function divide() {
        // implementation goes here
    }
}
/* Double Implementation */
class Double extends Number {
    public function add() {
        // implementation goes here
    }

    public function subtract() {
        // implementation goes here
    }

    public function multiply() {
        // implementation goes here
    }

    public function divide() {
        // implementation goes here
    }
}
/* Long Implementation */
class Long extends Number {
    public function add() {
        // implementation goes here
    }

    public function subtract() {
        // implementation goes here
    }

    public function multiply() {
        // implementation goes here
    }

    public function divide() {
        // implementation goes here
    }
}

$number = NumbersFactory::makeNumber( 'float', 12.5 );

清楚地区分使用工厂或工厂方法背后的思想是很重要的。 两者都旨在解决互斥的不同类型的对象创建问题。

让我们具体谈谈“工厂方法”:

首先,当您正在开发库或api时,这些库或api将用于进一步的应用程序开发,那么工厂方法是创建模式的最佳选择之一。原因;我们知道什么时候创建一个所需功能的对象,但对象的类型仍未确定,或者将根据传递的动态参数来决定。

Now the point is, approximately same can be achieved by using factory pattern itself but one huge drawback will introduce into the system if factory pattern will be used for above highlighted problem, it is that your logic of crating different objects(sub classes objects) will be specific to some business condition so in future when you need to extend your library's functionality for other platforms(In more technically, you need to add more sub classes of basic interface or abstract class so factory will return those objects also in addition to existing one based on some dynamic parameters) then every time you need to change(extend) the logic of factory class which will be costly operation and not good from design perspective. On the other side, if "factory method" pattern will be used to perform the same thing then you just need to create additional functionality(sub classes) and get it registered dynamically by injection which doesn't require changes in your base code.

interface Deliverable 
{
    /*********/
}

abstract class DefaultProducer 
{

    public void taskToBeDone() 
    {   
        Deliverable deliverable = factoryMethodPattern();
    }
    protected abstract Deliverable factoryMethodPattern();
}

class SpecificDeliverable implements Deliverable 
{
 /***SPECIFIC TASK CAN BE WRITTEN HERE***/
}

class SpecificProducer extends DefaultProducer 
{
    protected Deliverable factoryMethodPattern() 
    {
        return new SpecificDeliverable();
    }
}

public class MasterApplicationProgram 
{
    public static void main(String arg[]) 
    {
        DefaultProducer defaultProducer = new SpecificProducer();
        defaultProducer.taskToBeDone();
    }
}

GOF定义:

定义一个用于创建对象的接口,但是让子类来决定实例化哪个类。工厂方法允许类延迟实例化到子类。

一般例子:

public abstract class Factory<T> {

    public abstract T instantiate(Supplier<? extends T> supplier);

}

具体类

public class SupplierFactory<T> extends Factory<T> {

    @Override
    public T instantiate(Supplier<? extends T> supplier) {
        return supplier.get();
    }
}

实现

public class Alpha implements BaseInterface {
    @Override
    public void doAction() {
        System.out.println("The Alpha executed");
    }
}

public class Beta implements BaseInterface {
    @Override
    public void doAction() {
        System.out.println("The Beta executed");
    }
}

public interface BaseInterface {
    void doAction();
}

public class Main {
    public static void main(String[] args) {
        Factory<BaseInterface> secondFactory = new SupplierFactory<>();
        secondFactory.instantiate(Beta::new).doAction();
        secondFactory.instantiate(Alpha::new).doAction();
    }
}

短暂的优势

您正在分离可以变化的代码和不变的代码(即,使用简单工厂模式的优点仍然存在)。这种技术可以帮助您轻松地维护代码。 你的代码不是紧密耦合的;因此,你可以随时在系统中添加新的类,如Lion、Beer等,而无需修改现有的体系结构。因此,您遵循了“修改封闭,扩展开放”的原则。