设计模式之工厂模式
来源:互联网 发布:mysql count 性能优化 编辑:程序博客网 时间:2024/05/17 18:14
工作中,当我们需要一个对象的时候,一般我们都是直接new一个对象出来使用,那么new有什么不对劲吗?当使用new时,我们是在实例化一个具体类,而不是接口,我们已经知道代码绑着具体类会导致代码更脆弱,更缺乏弹性。其实,使用new并没有错,真正的问题是"改变"。针对接口编程,可以隔离掉以后系统可能发生的一大堆改变,如果针对接口编程,那么通过多态,它可以与任何新类实现改接口。而使用具体类时,一旦加入新的具体类,就必须改变代码。处于这种情况,工厂模式诞生了。
一.披萨商店
Pizza orderPizza(String type){ Pizza pizza; if(type.equals("cheese")){ pizza = new CheesePizza(); }else if(type.equals("greek")){ pizza = new GreekPizza(); }else if(type.equals("pepperoni")){ pizza = new PepperoniPizza(); } pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza;}
上面的代码是披萨店制作披萨的示例,这段代码通过type返回不同的披萨类型,不过当我们需要新加或者去掉一些披萨的时候,我们只能修改orderPizza的代码了。我们知道,我们应该将变化和不变的代码分离,所以我们需要把创建披萨对象的代码拿出来。
二.建立一个简单披萨工厂
public class PizzaStore{ SimplePizzaFactory factory; public PizzaStore(SimplePizzaFactory factory){ this.factory = factory; } Pizza orderPizza(String type){ Pizza pizza = factory.createPizza(type); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; }}
public class SimplePizzaFactory{ public Pizza createPizza(String type){ if(type.equals("cheese")){ pizza = new CheesePizza(); }else if(type.equals("greek")){ pizza = new GreekPizza(); }else if(type.equals("pepperoni")){ pizza = new PepperoniPizza(); } return pizza; }}
简单工厂有什么好处呢?看起来似乎只是把问题搬到另一个对象罢了,别忘了SimplePizzaFactory可以有许多的客户。虽然目前只看到orderPizza()方法使用,然而后续可能会有PizzaShopMenu等其他地方使用,所以把创建披萨的代码包装进一个类,当以后实现改变时,只需要修改这个类即可。简单工厂其实不是一个设计模式,反而比较像是一个编程习惯。
三.工厂方法
工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
我们看看如何用工厂方法模式修改我们的披萨商店
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);}
纽约风味的披萨商店
public class NYPizzaStore extends PizzaStore{ @Override Pizza createPizza(String type) { if(type .equals("cheese" )){ return new NYStypeCheesePizza(); } else if (type .equals("veggie" )){ return new NYStyleVeggiePizza(); } else if (type .equals("clam" )){ return new NYStyleClamPizza(); } return null ; }}
其实工厂方法模式看起来还是非常简单的,只是声明一个抽象方法来创建对象,具体的创建对象操作交给子类来实现,由子类决定要实例化的类是哪一个。工厂方法模式能够封装具体类型的实例化。
如果只有一个工厂方法的实现类时,工厂方法模式有什么优点呢?尽管只有一个具体创建者,工厂方法模式依然很有用,因为它帮助我们将产品的实现从使用中解耦,如果增加产品或者改变产品的实现,工厂类都不会受影响。
简单工厂和工厂方法之间有什么差异呢?他们看起来很类似,差别在于,在工厂方法中,返回披萨的类是子类。子类的确看起来很想简单工厂,简单工厂把全部的事情在一个地方都处理完了,然而工厂方法却是创建一个框架,让子类决定要如何实现。比方说,在工厂方法中,orderPizza()方法提供了一般的框架,以便创建披萨,orderPizza()方法依赖工厂方法创建具体类,并制造出实际的披萨。可通过继承PizzaStore类,决定实际制造的披萨是什么。简单工厂的做法,可以将对象的创建封装起来,但是简单工厂不具备工厂方法的弹性,因为简单工厂不能变更正在创建的产品。
四.抽象工厂
现在,我们要建造一个工厂来生成原料,这个工厂将负责创建原料家族中的每一种原料。也就是说,工厂将需要生成面团,酱料,芝士等。开始先为工厂定义一个接口,这个接口负责创建所有的原料。
public interface PizzaIngredientFactory { public Dough createDough(); public Sauce createSauce(); public Cheese createCheese();}
public class NYPizzaIngredientFactory implements PizzaIngredientFactory { @Override public Dough createDough() { return new ThinCrustDough(); } @Override public Sauce createSauce() { return new MarinataSauce(); } @Override public Cheese createCheese() { return new ReggiannoCheese(); }}
public abstract class Pizza { String name; Dough dough; Sauce sauce; Cheese cheese; List<String> toppings = new ArrayList<String>(); abstract void prepare(); void bake(){ System. out.println("Bake for 25 minutes at 350"); } void cut(){ System. out.println("Cutting the pizza into diagonal slices"); } void box(){ System. out.println("Place pizza in official PizzaStore box"); }}
public class NYStyleClamPizza extends Pizza{ PizzaIngredientFactory ingredientFactory; public NYStyleClamPizza(PizzaIngredientFactory ingredientFactory){ this.ingredientFactory = ingredientFactory ; } public NYStyleClamPizza(){ } @Override void prepare() { System. out.println("Preparing " +name ); dough = ingredientFactory.createDough(); sauce = ingredientFactory.createSauce(); cheese = ingredientFactory.createCheese(); }}
public class NYPizzaStore extends PizzaStore{ @Override Pizza createPizza(String type) { Pizza pizza = null; PizzaIngredientFactory ingredientFactory = new NYPizzaIngredientFactory(); if(type .equals("cheese" )){ pizza = new NYStypeCheesePizza(ingredientFactory ); pizza.setName( "New York Style Cheese Pizza"); } else if (type .equals("veggie" )){ pizza = new NYStyleClamPizza(ingredientFactory ); pizza.setName( "New York Style Veggie Pizza"); } else if (type .equals("clam" )){ pizza = new NYStyleClamPizza(ingredientFactory ); pizza.setName( "New York Style Clam Pizza"); } return pizza ; }}
我们对代码做了一连串的改变,我们引入新类型的工厂,也就是所谓的抽象工厂,来创建披萨原料家族。通过抽象工厂所提供的接口,可以创建产品的家族,利用这个接口书写代码,我们的代码将从实际工厂解耦。因为代码从实际的产品中解耦了,所以我们可以替换不同的工厂来取得不同的鱼腥味。
抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要知道实际产出的具体产品是什么。抽象工厂的方法经常以工厂方法的方式实现。
五.工厂方法和抽象工厂
工厂方法实现用的是继承,而抽象工厂是通过对象的组合。其实整个工厂方法模式,只不过就是通过子类来创建对象,用这种做法,客户只需要知道他们所使用的抽象类型就可以了,而由子类来负责决定具体类型。抽象工厂提供一个用来创建一个产品家族的抽象类型,这个类型的子类定义了产品被产生的方法,要想使用这个工厂,必须先实例化它,然后将它传入一个针对抽象类型锁写的代码中。所以抽象工厂可以把一群相关的产品集合起来。
对于抽象工厂,新增一个产品需要改变接口。
当你需要创建产品家族和想让制造的相关产品集合起来时,可以使用抽象工厂。
工厂方法可以把你的客户代码从需要实例化的具体类中解耦。或者如果你目前还不知道将来需要实例化哪些具体类时,可以使用工厂方法。
区别: 工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。
0 0
- 设计模式之工厂模式
- 设计模式之工厂模式
- 设计模式之工厂模式
- 设计模式之工厂模式
- 设计模式之工厂模式
- 设计模式之工厂模式
- 设计模式之---工厂模式
- 设计模式之工厂模式
- 设计模式之工厂模式
- 设计模式之工厂模式
- 设计模式之工厂模式
- 设计模式之-工厂模式
- 设计模式之工厂模式
- 设计模式之工厂模式
- 设计模式之工厂模式
- 设计模式之工厂模式
- 设计模式之 ------工厂模式
- 设计模式之工厂模式
- java基础提高篇--java的三大特性--继承
- kNN算法及实例(二)
- sas proc sql 基础入门 (原创作品,转载请注明出处 )
- Servlet需要注意的细节(重要)
- QT中的数据类型--转自<QtGlobal>
- 设计模式之工厂模式
- MySQL之alter语句用法总结
- 做好这五点轻松优化长尾关键词
- java源码中assert的基本用法
- jQuery
- Log4j 日志配置邮件实战
- IE浏览器没有网络
- Android 反编译教程
- Driver Test