问题描述
什么时候在对象中使用工厂方法而不是工厂类是一个好主意?
推荐答案
我喜欢考虑我的课程是"人",而模式是人们互相交谈的方式.
所以,对我来说,工厂模式就像招聘机构.您有一个需要可变数量的工人的人.这个人可能知道他们雇用的人需要的一些信息,但仅此而已.
因此,当他们需要新员工时,他们会打电话给招聘机构,并告诉他们他们需要什么.现在,要真正雇用某人,您需要了解很多东西 - 好处,资格验证等.但是,招聘人员不需要知道任何这些 - 招聘机构可以处理所有那.
以相同的方式,使用工厂允许消费者创建新对象,而不必知道其创建方式或依赖关系的详细信息 - 他们只需要提供他们实际想要的信息.
public interface IThingFactory { Thing GetThing(string theString); } public class ThingFactory : IThingFactory { public Thing GetThing(string theString) { return new Thing(theString, firstDependency, secondDependency); } }
因此,现在,事物的消费者可以得到东西,而不必知道事物的依赖性,除了来自消费者的字符串数据.
其他推荐答案
应将工厂方法视为构造函数的替代方法 - 主要是当构造函数不够表达时,即
class Foo{ public Foo(bool withBar); }
不像:
那样表现力class Foo{ public static Foo withBar(); public static Foo withoutBar(); }
当您需要一个复杂的过程来构建对象时,当构造需要您不需要实际类的依赖项时,当您需要构造不同的对象等时,很有用.
..其他推荐答案
我个人发现单独的工厂类以使人有意义的一种情况是,您试图创建的最终对象依赖其他几个对象.例如,在php中:假设您有一个House对象,依次具有Kitchen和a LivingRoom对象,并且LivingRoom对象也有TV对象.
实现此目的的最简单方法是让每个对象在其构造方法上创建他们的孩子,但是如果属性相对嵌套,当您的House失败时,您可能会花一些时间试图隔离失败的东西.
替代方法是执行以下(如果您喜欢幻想术语):
:$TVObj = new TV($param1, $param2, $param3); $LivingroomObj = new LivingRoom($TVObj, $param1, $param2); $KitchenroomObj = new Kitchen($param1, $param2); $HouseObj = new House($LivingroomObj, $KitchenroomObj);
在这里,如果创建House失败的过程只有一个地方可以看,但是每次想要一个新的House时都必须使用此块,这远非方便.输入工厂:
class HouseFactory { public function create() { $TVObj = new TV($param1, $param2, $param3); $LivingroomObj = new LivingRoom($TVObj, $param1, $param2); $KitchenroomObj = new Kitchen($param1, $param2); $HouseObj = new House($LivingroomObj, $KitchenroomObj); return $HouseObj; } } $houseFactory = new HouseFactory(); $HouseObj = $houseFactory->create();
感谢此处的工厂,创建House的过程是抽象的(因为当您只想创建House时,您不需要创建和设置每个依赖性)和同时设置集中式,这使维护更容易.还有其他原因为什么使用单独的工厂可以是有益的(例如可检验性),但是我发现这种特定用例以说明工厂类如何有用.
问题描述
When is it a good idea to use factory methods within an object instead of a Factory class?
推荐答案
I like thinking about design pattens in terms of my classes being 'people,' and the patterns are the ways that the people talk to each other.
So, to me the factory pattern is like a hiring agency. You've got someone that will need a variable number of workers. This person may know some info they need in the people they hire, but that's it.
So, when they need a new employee, they call the hiring agency and tell them what they need. Now, to actually hire someone, you need to know a lot of stuff - benefits, eligibility verification, etc. But the person hiring doesn't need to know any of this - the hiring agency handles all of that.
In the same way, using a Factory allows the consumer to create new objects without having to know the details of how they're created, or what their dependencies are - they only have to give the information they actually want.
public interface IThingFactory { Thing GetThing(string theString); } public class ThingFactory : IThingFactory { public Thing GetThing(string theString) { return new Thing(theString, firstDependency, secondDependency); } }
So, now the consumer of the ThingFactory can get a Thing, without having to know about the dependencies of the Thing, except for the string data that comes from the consumer.
其他推荐答案
Factory methods should be considered as an alternative to constructors - mostly when constructors aren't expressive enough, ie.
class Foo{ public Foo(bool withBar); }
is not as expressive as:
class Foo{ public static Foo withBar(); public static Foo withoutBar(); }
Factory classes are useful when you need a complicated process for constructing the object, when the construction need a dependency that you do not want for the actual class, when you need to construct different objects etc.
其他推荐答案
One situation where I personally find separate Factory classes to make sense is when the final object you are trying to create relies on several other objects. E.g, in PHP: Suppose you have a House object, which in turn has a Kitchen and a LivingRoom object, and the LivingRoom object has a TV object inside as well.
The simplest method to achieve this is having each object create their children on their construct method, but if the properties are relatively nested, when your House fails creating you will probably spend some time trying to isolate exactly what is failing.
The alternative is to do the following (dependency injection, if you like the fancy term):
$TVObj = new TV($param1, $param2, $param3); $LivingroomObj = new LivingRoom($TVObj, $param1, $param2); $KitchenroomObj = new Kitchen($param1, $param2); $HouseObj = new House($LivingroomObj, $KitchenroomObj);
Here if the process of creating a House fails there is only one place to look, but having to use this chunk every time one wants a new House is far from convenient. Enter the Factories:
class HouseFactory { public function create() { $TVObj = new TV($param1, $param2, $param3); $LivingroomObj = new LivingRoom($TVObj, $param1, $param2); $KitchenroomObj = new Kitchen($param1, $param2); $HouseObj = new House($LivingroomObj, $KitchenroomObj); return $HouseObj; } } $houseFactory = new HouseFactory(); $HouseObj = $houseFactory->create();
Thanks to the factory here the process of creating a House is abstracted (in that you don't need to create and set up every single dependency when you just want to create a House) and at the same time centralized which makes it easier to maintain. There are other reasons why using separate Factories can be beneficial (e.g. testability) but I find this specific use case to illustrate best how Factory classes can be useful.