Header First设计模式学习笔记——工厂模式
2014-06-22 23:48
369 查看
一、简单工厂
定义:定义一个创建对象的接口,但是由其子类决定要实例化的对象是哪一个,工厂方法让类的实例化推迟到子类。
通俗的来讲就是由工厂方法确定一个框架,具体的实现由其子类来完成。与简单工厂相比,简单工厂可是完成了整个对象的创建。
严格的来说简单工厂并不是一种设计模式,他更像是一种编程习惯。
代码说明一切!
1、这是一个简单工厂
2、这是一个pizza的store
我们可以看到,当我们需要一个pizza时并不需要知道该如何创建具体的pizza,我们只要调用一个简单工厂的方法,工厂就会给我们返回一个pizza,很炫酷!(更深一步,我们可以加入第一个模式——策略模式,也就是说可以动态的设置不同的简单工厂,从而让简单工厂返回不同的pizza)
其实,大家在写代码的时候都或多或少的用到过这个code习惯。比如说在写一些项目的时候,我们会额外加一个叫作utils的包,里面基本上都是一些类的静态方法或者叫做工具函数(像一些提取特定字符串啊等)。这其实就是静态工厂(我们不需要创建对象就可以通过其类名调用想用的工具函数),而与普通的简单工厂相比,他不能通过继承改变创建对象的行为。
二、工厂方法模式
看完简单工厂,你可能会说,哟,不错哦!那我们为什么还要使用工厂方法模式呢?
仔细想想,假如我们又出新产品了,不仅有cheese, peperoni, clam, vegie的pizza还有什么白菜,萝卜,西瓜pizza,意思就是说我们的产品可是变化着的,那问题来了,我们会不可避免的修改代码,什么?修改类的代码!那就不好了!head first 曾提及过一个原则叫做开放关闭原则,大概的意思是说,类应该对扩展开放(你可以通过继承来扩展这个类),而对修改关闭(你要是想要修改我这个类,我就不愿意了)。
很明显啊!简单工厂要想实现产品的更新工作,就必须要违反这个原则!那肿么办呢?好吧,来看看工厂方法模式。
来看看我们新的PizzaStore(这是一个abstract类,不能创建这个类的对象)
再来看两个他的子类(通过继承我们实现了超类代码和子类创建对象的代码的解耦)
检验代码
这样,我们通过不同的store(不同的子类)相同的orderPizza方法就可以创造出不同的pizza!
三、抽象工厂
定义:提供一个接口,用于创建一组相关的或者相依赖的的家族,而不需明确指明具体类。
在我理解就是纯粹的工厂方法的叠加,他提供一个创建一系列相关联的一组对象的接口,由实现这个接口的类来具体实现各个对象的创建工作
先来定义一个接口PizzaIngredientFactory,他定义了一系列的创建Pizza材料的方法
看他的两个子类(准确的说是实现了这个接口的类)
看看我们的CheesePizza类和ClamPizza类的创建
再来看看改进后的NYPPizzaStore
对于此时的NYPPizzaStore,创建具体的Pizza的时候我们就要传入一个PizzaIngredientFactory对象了!
四、三者的比较
对于简单工厂,所有的对象的创建由简单工厂全权负责,只要最后可以给我们返回一个我们需要的对象就可以了,他的运用是通过组合的方式实现的;
对于工厂方法,抽象的父类提供一个对象创建的接口,具体对象的创建推迟到子类中去实现,从而实现扩展;
对于抽象工厂,可以看成是工厂方法的叠加,他提供了创建一系列相关的对象的接口,由各个子类去实现,他的运用也是通过组合的方式实现的。
定义:定义一个创建对象的接口,但是由其子类决定要实例化的对象是哪一个,工厂方法让类的实例化推迟到子类。
通俗的来讲就是由工厂方法确定一个框架,具体的实现由其子类来完成。与简单工厂相比,简单工厂可是完成了整个对象的创建。
严格的来说简单工厂并不是一种设计模式,他更像是一种编程习惯。
代码说明一切!
1、这是一个简单工厂
package my.oschina.net.design.factory; public class SimplePizzaFactory { /** * 根据传入的type参数,返回相应的pizza * @param type * @return */ public Pizza createPizza(String type) { Pizza pizza = null; if (type.equals("cheese")) { pizza = new CheesePizza(); } else if (type.equals("pepperoni")) { pizza = new PepperoniPizza(); } else if (type.equals("clam")) { pizza = new ClamPizza(); } else if (type.equals("veggie")) { pizza = new VeggiePizza(); } return pizza; } }
2、这是一个pizza的store
package my.oschina.net.design.factory; public class PizzaStore { //通过组合的使用,加上一个简单工厂SimplePizzaFactory的引用,用于创建pizza SimplePizzaFactory factory; public PizzaStore(SimplePizzaFactory factory) { this.factory = factory; } public Pizza orderPizza(String type) { Pizza pizza; //调用简单工厂SimplePizzaFactory的createPizza(type)方法创建pizza pizza = factory.createPizza(type); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } }
我们可以看到,当我们需要一个pizza时并不需要知道该如何创建具体的pizza,我们只要调用一个简单工厂的方法,工厂就会给我们返回一个pizza,很炫酷!(更深一步,我们可以加入第一个模式——策略模式,也就是说可以动态的设置不同的简单工厂,从而让简单工厂返回不同的pizza)
其实,大家在写代码的时候都或多或少的用到过这个code习惯。比如说在写一些项目的时候,我们会额外加一个叫作utils的包,里面基本上都是一些类的静态方法或者叫做工具函数(像一些提取特定字符串啊等)。这其实就是静态工厂(我们不需要创建对象就可以通过其类名调用想用的工具函数),而与普通的简单工厂相比,他不能通过继承改变创建对象的行为。
二、工厂方法模式
看完简单工厂,你可能会说,哟,不错哦!那我们为什么还要使用工厂方法模式呢?
仔细想想,假如我们又出新产品了,不仅有cheese, peperoni, clam, vegie的pizza还有什么白菜,萝卜,西瓜pizza,意思就是说我们的产品可是变化着的,那问题来了,我们会不可避免的修改代码,什么?修改类的代码!那就不好了!head first 曾提及过一个原则叫做开放关闭原则,大概的意思是说,类应该对扩展开放(你可以通过继承来扩展这个类),而对修改关闭(你要是想要修改我这个类,我就不愿意了)。
很明显啊!简单工厂要想实现产品的更新工作,就必须要违反这个原则!那肿么办呢?好吧,来看看工厂方法模式。
来看看我们新的PizzaStore(这是一个abstract类,不能创建这个类的对象)
package my.oschina.net.design.factory; /** * 这是一个抽象类,通过继承实现createPizza方法, * 我们可以创建不同的对象 * @author Eswin * */ public abstract class PizzaStore { //这里定义一个工厂方法 abstract Pizza createPizza(String item); public Pizza orderPizza(String type) { Pizza pizza = createPizza(type); System.out.println("--- Making a " + pizza.getName() + " ---"); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } }
再来看两个他的子类(通过继承我们实现了超类代码和子类创建对象的代码的解耦)
package my.oschina.net.design.factory; public class ChicagoPizzaStore extends PizzaStore { Pizza createPizza(String item) { if (item.equals("cheese")) { return new ChicagoStyleCheesePizza(); } else if (item.equals("veggie")) { return new ChicagoStyleVeggiePizza(); } else if (item.equals("clam")) { return new ChicagoStyleClamPizza(); } else if (item.equals("pepperoni")) { return new ChicagoStylePepperoniPizza(); } else return null; } } package my.oschina.net.design.factory; public class NYPizzaStore extends PizzaStore { Pizza createPizza(String item) { if (item.equals("cheese")) { return new NYStyleCheesePizza(); } else if (item.equals("veggie")) { return new NYStyleVeggiePizza(); } else if (item.equals("clam")) { return new NYStyleClamPizza(); } else if (item.equals("pepperoni")) { return new NYStylePepperoniPizza(); } else return null; } }
检验代码
package my.oschina.net.design.factory; public class PizzaTestDrive { public static void main(String[] args) { PizzaStore nyStore = new NYPizzaStore(); PizzaStore chicagoStore = new ChicagoPizzaStore(); Pizza pizza = nyStore.orderPizza("cheese"); System.out.println("Ethan ordered a " + pizza.getName() + "\n"); pizza = chicagoStore.orderPizza("cheese"); System.out.println("Joel ordered a " + pizza.getName() + "\n"); pizza = nyStore.orderPizza("clam"); System.out.println("Ethan ordered a " + pizza.getName() + "\n"); pizza = chicagoStore.orderPizza("clam"); System.out.println("Joel ordered a " + pizza.getName() + "\n"); } }
这样,我们通过不同的store(不同的子类)相同的orderPizza方法就可以创造出不同的pizza!
三、抽象工厂
定义:提供一个接口,用于创建一组相关的或者相依赖的的家族,而不需明确指明具体类。
在我理解就是纯粹的工厂方法的叠加,他提供一个创建一系列相关联的一组对象的接口,由实现这个接口的类来具体实现各个对象的创建工作
先来定义一个接口PizzaIngredientFactory,他定义了一系列的创建Pizza材料的方法
package my.oschina.net.design.abstract_actory; public interface PizzaIngredientFactory { public Dough createDough(); public Sauce createSauce(); public Cheese createCheese(); public Veggies[] createVeggies(); public Pepperoni createPepperoni(); public Clams createClam(); }
看他的两个子类(准确的说是实现了这个接口的类)
package my.oschina.net.design.abstract_actory; public class NYPizzaIngredientFactory implements PizzaIngredientFactory { public Dough createDough() { return new ThinCrustDough(); } public Sauce createSauce() { return new MarinaraSauce(); } public Cheese createCheese() { return new ReggianoCheese(); } public Veggies[] createVeggies() { Veggies veggies[] = { new Garlic(), new Onion(), new Mushroom(), new RedPepper() }; return veggies; } public Pepperoni createPepperoni() { return new SlicedPepperoni(); } public Clams createClam() { return new FreshClams(); } } package my.oschina.net.design.abstract_actory; public class ChicagoPizzaIngredientFactory implements PizzaIngredientFactory { public Dough createDough() { return new ThickCrustDough(); } public Sauce createSauce() { return new PlumTomatoSauce(); } public Cheese createCheese() { return new MozzarellaCheese(); } public Veggies[] createVeggies() { Veggies veggies[] = { new BlackOlives(), new Spinach(), new Eggplant() }; return veggies; } public Pepperoni createPepperoni() { return new SlicedPepperoni(); } public Clams createClam() { return new FrozenClams(); } }
看看我们的CheesePizza类和ClamPizza类的创建
package my.oschina.net.design.abstract_actory; public class CheesePizza extends Pizza { //这里组合了一个PizzaIngredientFactory对象的引用,用于提供不同的原料 PizzaIngredientFactory ingredientFactory; /** * 通过传入一个PizzaIngredientFactory原料工厂,我们可以在制作Pizza的时候动态的产生所需要的原料 * @param ingredientFactory */ public CheesePizza(PizzaIngredientFactory ingredientFactory) { this.ingredientFactory = ingredientFactory; } void prepare() { System.out.println("Preparing " + name); dough = ingredientFactory.createDough(); sauce = ingredientFactory.createSauce(); cheese = ingredientFactory.createCheese(); } } package my.oschina.net.design.abstract_actory; public class ClamPizza extends Pizza { PizzaIngredientFactory ingredientFactory; public ClamPizza(PizzaIngredientFactory ingredientFactory) { this.ingredientFactory = ingredientFactory; } void prepare() { System.out.println("Preparing " + name); dough = ingredientFactory.createDough(); sauce = ingredientFactory.createSauce(); cheese = ingredientFactory.createCheese(); clam = ingredientFactory.createClam(); } }
再来看看改进后的NYPPizzaStore
package my.oschina.net.design.abstract_actory; public class NYPizzaStore extends PizzaStore { protected Pizza createPizza(String item) { Pizza pizza = null; PizzaIngredientFactory ingredientFactory = new NYPizzaIngredientFactory(); if (item.equals("cheese")) { pizza = new CheesePizza(ingredientFactory); pizza.setName("New York Style Cheese Pizza"); } else if (item.equals("veggie")) { pizza = new VeggiePizza(ingredientFactory); pizza.setName("New York Style Veggie Pizza"); } else if (item.equals("clam")) { pizza = new ClamPizza(ingredientFactory); pizza.setName("New York Style Clam Pizza"); } else if (item.equals("pepperoni")) { pizza = new PepperoniPizza(ingredientFactory); pizza.setName("New York Style Pepperoni Pizza"); } return pizza; } }
对于此时的NYPPizzaStore,创建具体的Pizza的时候我们就要传入一个PizzaIngredientFactory对象了!
四、三者的比较
对于简单工厂,所有的对象的创建由简单工厂全权负责,只要最后可以给我们返回一个我们需要的对象就可以了,他的运用是通过组合的方式实现的;
对于工厂方法,抽象的父类提供一个对象创建的接口,具体对象的创建推迟到子类中去实现,从而实现扩展;
对于抽象工厂,可以看成是工厂方法的叠加,他提供了创建一系列相关的对象的接口,由各个子类去实现,他的运用也是通过组合的方式实现的。
相关文章推荐
- Head First 设计模式学习笔记(4)---工厂模式
- 设计模式学习笔记三:简单工厂(Simple Factory)
- 设计模式学习笔记之(一、工厂模式)
- 设计模式学习笔记(四)之工厂模式(Factory)
- 设计模式学习笔记——简单工厂(Simple Factory)
- 设计模式学习笔记:factory method(工厂方法)
- .net设计模式之工厂模式学习笔记
- 设计模式学习笔记-工厂方法
- java 设计模式 学习笔记(1) - 简单工厂模式
- 设计模式学习笔记:就一句话的创建实例是如何演变成工厂模式的?
- 学习笔记之设计模式:抽象工厂
- 设计模式学习笔记之工厂模式
- 设计模式学习笔记-----工厂模式
- C#面向对象设计模式纵横谈 学习笔记3 Abstract Factory 抽象工厂
- C#设计模式学习笔记---简单工厂模式
- HeadFirst 设计模式学习笔记4--工厂模式
- 设计模式学习笔记(二)--简单工厂模式
- 简单工厂模式(未完成)——小鸟学习设计模式笔记系列
- 设计模式学习笔记(一):抽象工厂
- 设计模式学习笔记六:.NET反射工厂