1.定义:工厂模式是 我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式。著名的jive论坛,就大量使用了工厂模式,工厂模式在java程序系统可以说是随处可见。因为工厂模式就相当于创建实例化对象的new,我们经常要根据累class生成实力对象,如 A a = new A() 工厂模式也是用来创建实例对象的,所以在new时候要多大考虑是否可以用工厂模式实现,虽然这样做会多做一些工作,但是会给你的系统带来更大的可扩展性和尽量少的修改量
下面是我阅读 head first 设计模式学习归纳总结的关于工厂模式的由浅入深的分析,如有问题,请多多指教~~~
假设 我开设一家披萨店 ,那么关于披萨代码似乎可以这样实现
pizza orderPizza(){
pizza pizza = new Pizza();
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
pizza.pizza();
} //为了让系统有弹性,我们很希望这是一个抽象类或者接口。但如果这样,这些类或者接口就无法直接实例化
但是你需要更多的披萨类型。。。。。。 你就会如下这样做
pizza orderPizza(string type){
pizza pizza;
if(type.equals("cheese")){
pizza = new cheesePizza();
}else if(type.equals("greek")){
pizza = new greekPizza();
}
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
pizza.pizza();
} //根据pizza类型,我们去实例化具体的披萨类,然后将其赋值给pizza实例变量。请注意,这里的任何披萨都必须实现pizza接口
上面代码解决了增加不同类型的披萨 ,但是压力来源于日益增加的披萨类型 ,由简单几种变成十几种 二十 几种、三十几种 、成千上万种时候呢。。。。又同时有一些销量不好的披萨 需要去除时候 我们怎么办?
我们每次 在 orderPizza中 去除 下架的pizza 增加新增的pizza 很明显 如果实例化“某些”具体类,将使orderpizza 出现问题,而且我们也无法让orderPizza() 对修改关闭;但是,现在我们已经知道那些会改变,那些不会改变,该是使用封装的时候了。
封装创建对象的代码 。。。。
orderpizza 里的new :
if(type.equals("cheese")){
pizza = new cheesePizza();
}else if(type.equals("greek")){
pizza = new greekPizza();
}
单独抽象出去。。。。 放到另一个对象里去,这个对象只管如何创建披萨,如果任何对象想创建披萨直接找它就对了
我们称这个新的对象就是“工厂” factory
工厂:处理创建对象的细节,一旦有了披萨工厂,orderpizza()就变成这个工厂对象的客户了,需要什么披萨 就找工厂去做,自身不需要知道披萨的类型,下面我们建立一个简单的披萨工厂
我们要封装一个工厂类为所有类型的披萨生产披萨
public class simlePizzaFactory{
public pizza createPizza(string type){
pizza pizza =null;
}
if(type.equals("cheese")){
pizza = new cheesePizza();
}else if(.....){
......
}.....
return pizza ;
} //大家一定看出这样做其实并没有改变什么 只不过是把问题从orderPizza中拿出 依然也是以披萨的类型为参数的。
———————-现在我们重新做一个披萨类pizzaStore——————-
是时候修改我们的客户代码了,我们所要的就是仰仗工厂为我们创建披萨,要这样改变:
pizza orderStore(){
simplePizzaFactory factory ;
public PizzaStroe(simplePizzaFactory factory){
this.factory = faactory;
}
pubic Pizza orderPizza(string type){
pizza pizza;
pizza = factory.createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
pizza.pizza();
return pizza;
}
//这里是其他的方法
} //注意这里我们把new 操作换成了工厂的创建披萨的方法函数,这里不再使用具体的实例化
定义简单的工厂
简单的工厂模式不是一个设计模式,反而比较像是一种编程习惯。但由于经常被使用,所以我们给它一个“head first pattern 荣誉奖“。 有一些开发人员的确是把这个编程习惯当成是工厂模式,当你下次和另一个开发人员之间无话可说的时候,这应当是打破沉默的不错话题。
不要因为简单工厂不是一个”真正的“模式,就忽略了它的用法。让我们来看看新的披萨类图:
这是我们具体产品每一个产品必须要实现pizza的接口 ,并设计成一个具体类,这样一来就可以被工厂创建,并返回给客户。
加盟披萨店
我们已经有一个做法。。。。
如果利用simplepizzafactory 写出几种不同的工厂,分别是NYpizzafactory、ChicagoPizzafactory、CaliforniaPizzafactory,那么各地加盟店都有适合的工厂可以使用,这是一种做法
但是我们想要多一些质量控制。。。。。
在推广simplepizzafactory 时,你会发现 加盟店的确是采用你的工厂创建的,但是其他的呢,烘烤的做法有差异、不要切片、使用其它厂商的盒子。。。。。
所以这个时候你希望能够建立一个框架,把加盟店和创建披萨捆绑在一起的时候又保持一定弹性。
给披萨店使用的框架
public abstract class PizzaStore{
public pizza orderPizza(string type){
pizza pizza;
pizza = createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
abstract pizza createPizza(string type);
//现在把工厂对象移回这个方法里面,在pizzastore里面工厂方法是抽象的。
}
允许子类做决定
当orderpizza()调用createPizza()时,某个披萨子类奖负责创建披萨。做哪一种披萨呢?当然由具体的披萨店决定。。
优缺点:
优点:克服了简单工厂违背开放-封闭原则的缺点,又保留了封装对象创建过程的优点,降低客户端和工厂的耦合性,所以说“工厂模式”是“简单工厂模式”的进一步抽象和推广。
缺点:每增加一个产品,相应的也要增加一个子工厂,加大了额外的开发量。