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
它与子类有什么关系?我应该使用子类做什么呢?
有人能给我举个例子吗?
你的
(我假设你正在使用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,但返回的实现的实际类型(因此是子类引用)是工厂的责任。在示例中,工厂返回
工厂还有其他的习惯用法,比如工厂有一个API,工厂的具体实现不接受像我的例子中那样的
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(); } } |
在这个类中,
1 2 3 4 | ProductFactory* factory = new BookProductFactory(); Product* p1 = factory->Make(); // p1 is a Book delete p1; 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 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; |
当您像我在原始示例中那样使用
工厂模式仅仅意味着有一个工厂类或方法负责为您创建对象,而不是您自己实例化它们。就像汽车是在工厂里制造的,所以你不必这样做。
它与子类无关,但是作者可能试图说,工厂通常可以根据参数返回您派生的基类实现,因为该子类可以执行您在参数中要求的操作。
例如,webrequest.create("http://www.example.com")将返回httpwebrequest,而webrequest.create("ftp://www.example.com")将返回ftpwebrequest,因为两者具有不同的协议,这些协议由不同的类实现,但公共接口是相同的,因此此决定不必由我的API的使用者作出。
简单和简短:
在工厂中,检查请求哪个"子类"来实例化so
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++。
我只能假设他的意思是:
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 |
但是,这不是创建工厂的标准方法。