设计模式之->工厂模式

来源:互联网 发布:淘宝怎么生成数据包 编辑:程序博客网 时间:2024/05/16 08:15

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 里的newif(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 荣誉奖“。 有一些开发人员的确是把这个编程习惯当成是工厂模式,当你下次和另一个开发人员之间无话可说的时候,这应当是打破沉默的不错话题。
不要因为简单工厂不是一个”真正的“模式,就忽略了它的用法。让我们来看看新的披萨类图:

Created with Raphaël 2.1.0pizzastorepizzastoresimplePizzaFactorysimplePizzaFactorypizzastore:orderPizza() 是工厂的客户simplePizzaFactory:createPizza()声明为静态的工厂客户通过simplePizzaFactory获取批准实例
Created with Raphaël 2.1.0pizzapizzasimplePizzaFactorysimplePizzaFactoryprepare()、bake()、 cut()、 box()工厂客户通过simplePizzaFactory获取批准实例cheesepiazza 、veggiepizza、clampizza、pepperonipizza

这是我们具体产品每一个产品必须要实现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()时,某个披萨子类奖负责创建披萨。做哪一种披萨呢?当然由具体的披萨店决定。。

优缺点:
优点:克服了简单工厂违背开放-封闭原则的缺点,又保留了封装对象创建过程的优点,降低客户端和工厂的耦合性,所以说“工厂模式”是“简单工厂模式”的进一步抽象和推广。

缺点:每增加一个产品,相应的也要增加一个子工厂,加大了额外的开发量。

0 0