1.定义
定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。
2.类图
3.代码示例
1 package com.zhaoyangwoo.factorymethod; 2 3 /** 4 * Created by john on 16/5/1. 5 * @author wuzhaoyango 6 * <p> 7 * This is a demo for factoryMethod 8 * </p> 9 * <p> 10 * 工厂方法:一抽象产品类派生出多个具体产品类;一抽象工厂类派生出多个具体工厂类;每个具体工厂类只能创建一个具体产品类的实例。 11 * 即定义一个创建对象的接口(即抽象工厂类),让其子类(具体工厂类)决定实例化哪一个类(具体产品类)。“一对一”的关系。 12 * </p> 13 */ 14 public class FactoryMethod { 15 16 private static Factory factoryA,factoryB; 17 private static Product productA,productB; 18 public static void main(String[] args) { 19 factoryA = new FactoryA(); 20 factoryB = new FactoryB(); 21 productA = factoryA.create(); 22 productB = factoryB.create(); 23 productA.getName(); 24 productB.getName(); 25 } 26 } 27 28 29 interface Product{ 30 void getName(); 31 } 32 33 interface Factory{ 34 Product create(); 35 } 36 37 class ProductA implements Product{ 38 39 @Override 40 public void getName() { 41 System.out.println("I'm productA"); 42 } 43 } 44 45 class ProductB implements Product{ 46 47 @Override 48 public void getName() { 49 System.out.println("I'm productB"); 50 } 51 } 52 53 class FactoryA implements Factory { 54 55 @Override 56 public Product create() { 57 return new ProductA(); 58 } 59 } 60 61 class FactoryB implements Factory { 62 63 @Override 64 public Product create() { 65 return new ProductB(); 66 } 67 }
4.扩展:简单工厂模式
4.1 类图
4.2 代码示例
1 package com.zhaoyangwoo.simplefactory; 2 3 /** 4 * Created by john on 16/5/1. 5 * 简单工厂实现类,ConcreteFactory是"上帝类",这个设计模式是工厂方法的一种扩展,实际使用也比较多,但是 6 * 它并不满足开闭原则,如果拓展类一种新的产品,例如ProductC,那么必须修改create方法的判断条件,别无他法. 7 * 这并无影响它的广泛使用,所以原则是死的,编码是活的. 8 */ 9 public class SimpleFactory { 10 public static void main(String[] args){ 11 Product product = ConcreteFactory.create(ProductA.class); 12 product.getName(); 13 } 14 } 15 16 class ConcreteFactory { 17 public static Product create(Class t) { 18 if(t.equals(ProductA.class)){ 19 return new ProductA(); 20 }else if(t.equals(ProductB.class)){ 21 return new ProductB(); 22 }else { 23 throw new IllegalArgumentException("参数错误"); 24 } 25 } 26 } 27 interface Product{ 28 void getName(); 29 } 30 31 class ProductA implements Product { 32 33 @Override 34 public void getName() { 35 System.out.println("I'm productA"); 36 } 37 } 38 39 class ProductB implements Product { 40 41 @Override 42 public void getName() { 43 System.out.println("I'm productB"); 44 } 45 }
5.应用场景举例
- 创建复杂对象,隔离对象创建的具体过程
- 一个类不知道它所需要的对象的类:客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体的产品对象由具体工厂类创建;客户端需要知道创建具体产品的工厂类。
6.JDK源码中的模式实现
还记得我们在单例模式中提到的Calendar.getInstance() 吗?它实际上就是工厂方法的一个典型实现。我们再来看看源码
1 public static Calendar getInstance(TimeZone zone, 2 Locale aLocale) 3 { 4 return createCalendar(zone, aLocale); 5 } 6 7 private static Calendar createCalendar(TimeZone zone, 8 Locale aLocale) 9 { 10 CalendarProvider provider = 11 LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale) 12 .getCalendarProvider(); 13 if (provider != null) { 14 try { 15 return provider.getInstance(zone, aLocale); 16 } catch (IllegalArgumentException iae) { 17 // fall back to the default instantiation 18 } 19 } 20 21 Calendar cal = null; 22 23 //通过判断条件来决定用怎样的子类来实例化父类 24 if (aLocale.hasExtensions()) { 25 String caltype = aLocale.getUnicodeLocaleType("ca"); 26 if (caltype != null) { 27 switch (caltype) { 28 case "buddhist": 29 cal = new BuddhistCalendar(zone, aLocale); 30 break; 31 case "japanese": 32 cal = new JapaneseImperialCalendar(zone, aLocale); 33 break; 34 case "gregory": 35 cal = new GregorianCalendar(zone, aLocale); 36 break; 37 } 38 } 39 } 40 41 //通过判断条件来决定用怎样的子类来实例化父类 42 if (cal == null) { 43 if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") { 44 cal = new BuddhistCalendar(zone, aLocale); 45 } else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja" 46 && aLocale.getCountry() == "JP") { 47 cal = new JapaneseImperialCalendar(zone, aLocale); 48 } else { 49 cal = new GregorianCalendar(zone, aLocale); 50 } 51 } 52 return cal; 53 }