工厂方法设计模式

factory method design pattern

根据这本书:

The essence of the Factory Pattern is to"Define an interface for
creating an object, but let the subclasses decide which class to
instantiate. The Factory method lets a class defer instantiation to
subclasses.

假设我有一个创造者类:

1
2
3
4
5
6
7
8
9
class Product; //this is what the Factory Method should return
class Creator {
    public:
        Creator()   //ctor
        { //... }

        virtual Product make(//args)
        { //... }
}

好吧,那是我的创造者课程,但我不明白

The Factory method lets a class defer instantiation to subclasses

它与子类有什么关系?我应该使用子类做什么呢?

有人能给我举个例子吗?


你的Creator班是工厂。让我们称之为ProductFactory,以便使示例更加明确。

(我假设你正在使用C++)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Book : public Product
{
};

class Computer : public Product
{
};

class ProductFactory
{
public:
  virtual Product* Make(int type)
  {
    switch (type)
    {
      case 0:
        return new Book();
      case 1:
        return new Computer();
        [...]
    }
  }
}

这样称呼它:

1
2
3
4
ProductFactory factory = ....;
Product* p1 = factory.Make(0); // p1 is a Book*
Product* p2 = factory.Make(1); // p2 is a Computer*
// remember to delete p1 and p2

所以,要回答你的问题:

What does it have to do with subclasses? And what am I supposed to use
subclasses for?

工厂模式的定义是工厂为创建特定类型的实例(通常是接口或抽象类)定义了一个公共API,但返回的实现的实际类型(因此是子类引用)是工厂的责任。在示例中,工厂返回Product个实例,其中BookComputer是有效的子类。

工厂还有其他的习惯用法,比如工厂有一个API,工厂的具体实现不接受像我的例子中那样的type,但是它们与返回的实例类型相结合,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class ProductFactory
{
public:
  virtual Product* Make() = 0;
}

class BookProductFactory : public ProductFactory
{
public:
    virtual Product* Make()
    {
      return new Book();
    }
}

在这个类中,BookProductFactory总是返回Book个实例。

1
2
3
4
ProductFactory* factory = new BookProductFactory();
Product* p1 = factory->Make(); // p1 is a Book
delete p1;
delete factory;

为了说明这一点,由于Abstract FactoryFactory method设计模式之间似乎有点混淆,我们来看一个具体的例子:

使用抽象工厂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class ProductFactory {
protected:
  virtual Product* MakeBook() = 0;
  virtual Product* MakeComputer() = 0;
}

class Store {
public:
   Gift* MakeGift(ProductFactory* factory) {
     Product* p1 = factory->MakeBook();
     Product* p2 = factory->MakeComputer();
     return new Gift(p1, p2);
   }
}

class StoreProductFactory : public ProductFactory {
protected:
  virtual Product* MakeBook() { return new Book(); }
  virtual Product* MakeComputer() { return new Computer(); }
}

class FreeBooksStoreProductFactory : public StoreProductFactory {
protected:
  virtual Product* MakeBook() {
    Book* b = new FreeBook(); // a FreeBook is a Book with price 0
    return b;
  }
}

使用方法如下:

1
2
3
4
5
6
Store store;
ProductFactory* factory = new FreeBooksStoreProductFactory();
Gift* gift = factory->MakeGift(factory);
// gift has a FreeBook (Book with price 0) and a Computer
delete gift;
delete factory;

使用工厂方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Store {
public:
   Gift* MakeGift() {
     Product* p1 = MakeBook();
     Product* p2 = MakeComputer();
     return new Gift(p1, p2);
   }

 protected:
   virtual Product* MakeBook() {
     return new Book();
   }

   virtual Product* MakeComputer() {
     return new Computer();
   }
}

class FreeBooksStore : public Store {
protected:
  virtual Product* MakeBook() {
    Book* b = new FreeBook(); // a FreeBook is a Book with price 0
    return b;
  }
}

使用方法如下:

1
2
3
4
5
Store* store = new FreeBooksStore();
Gift* gift = store->MakeGift();
// gift has a FreeBook (Book with price 0) and a Computer
delete gift;
delete store;

当您像我在原始示例中那样使用type鉴别器时,我们使用parametized factory methods—一种知道如何创建不同类型对象的方法。但这可能出现在Abstract FactoryFactory method模式中。一个简单的技巧:如果您要扩展工厂类,那么您将使用抽象工厂。如果使用创建方法扩展类,则使用工厂方法。


工厂模式仅仅意味着有一个工厂类或方法负责为您创建对象,而不是您自己实例化它们。就像汽车是在工厂里制造的,所以你不必这样做。

它与子类无关,但是作者可能试图说,工厂通常可以根据参数返回您派生的基类实现,因为该子类可以执行您在参数中要求的操作。

例如,webrequest.create("http://www.example.com")将返回httpwebrequest,而webrequest.create("ftp://www.example.com")将返回ftpwebrequest,因为两者具有不同的协议,这些协议由不同的类实现,但公共接口是相同的,因此此决定不必由我的API的使用者作出。


简单和简短:

在工厂中,检查请求哪个"子类"来实例化so "let the subclasses decide which class to instantiate"。(在必须做出决定的工厂类中使用条件语句。)

"define an interface or abstract class for creating an object"。显然,您将对象存储到接口的引用中,客户机不知道返回哪个具体类的对象。(所以您定义了一个接口来创建一个对象)。


product make()将根据特定条件生成正确的产品类型(子类),并将实际实例化"延迟"到特定的产品。

(伪代码)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class Product
{
    public static Product Make()
    {
        switch(day_of_week)
        {
           case Monday: return new Honey(1.1);
           case Wednesday: return new Milk(3.6);
           case Thurday: return new Meat(0.5);
           case Friday: return new Vegetable(1.3);
           case Saturday: return new Vegetable(2.3); // more expensive on saturday, only factory need to know
           default: return null; // off day!
        }
    }

    // returns price based on underlying product type and hidden/auto conditions (days of week)
    public virtual void GetPrice() { return Price; }

    // sometimes a factory can accept a product type enum
    // From API POV, this is easier at a glance to know avaliable types.
    pubic enum Type { Milk, Honey, Meat, Vegetable };

    public static Product Make(Type, Day)
    {
        // create the specified type for the specified day.
    }
}

public class Honey : Product { Price = arg; }
public class Milk : Product { Price = arg; }
public class Meat : Product { Price = arg; }
public class Vegetable : Product { Price = arg; }

工厂隐藏了构造各种产品类型所需的条件详细信息。其次,从API用户的角度来看,imho通常更容易看到产品类型(通常来自枚举),并且更容易从单个创建点创建产品类型。


我也有同样的困惑,"让子类决定要实例化哪个类"——因为在实现工厂方法中,使用new创建一个对象"——我指的是head-first设计模式书,其中它清楚地说明了这一点,如下所示-"正如在官方定义中,你会经常听到开发人员说让子类决定要实例化哪个类。他们说"决定"不是因为模式允许子类自己决定运行时,而是因为创建者类是在不知道将要创建的实际产品的情况下编写的,这完全由选择决定。"使用的子类"


在伪代码中提供这样的示例有点令人困惑,模式依赖于语言。你的例子看起来像C++,但是它在C++中是无效的,因为EDCOX1×14是通过值返回EDCOX1×2的。这完全违背了EDCOX1(16)的主要目标——将引用(C++案例中的指针)返回基类。有些答案是C或Java(我猜),而其他的则是C++。

Factory模式依赖于多态性。关键是返回对基本Product类的引用。Factory的子类将创建具体类的实例。


我只能假设他的意思是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Product; //this is what the Factory Method should return
class Box : Product;

class Creator {
    public:
        Creator()   //ctor
        { //... }

        virtual Product* make(//args) = 0;
};

class BoxCreator{
    public:
        BoxCreator()
        {}
        virtual Product* make()
        {}
};

Creator* pCreator = new BoxCreator;
Product* pProduct = pCreator->make(); //will create a new box

但是,这不是创建工厂的标准方法。