简单工厂模式

又称静态工厂方法模式(Static Factory Method Pattern)

分析实现步骤

将在类中直接创建对象(new),提取到一个公共的工厂类中,达到创建对象和业务类解耦目的

代码实现

image.png

  1. 定义抽象类
  2. 实现具体类
  3. 定义简单工厂类
  4. 实现预定方法
  5. 客户端测试
  6. 分析

定义简单工厂类

  1. /**
  2. * 简单工厂模式
  3. */
  4. public class SimpleFactory {
  5. public static AbstractCake createCake(String orderType) {
  6. AbstractCake cake = null;
  7. if (orderType.equals("水果")) {
  8. cake = new fruitCake();
  9. cake.setName(orderType + "蛋糕 ");
  10. } else if (orderType.equals("奶油")) {
  11. cake = new CreamCake();
  12. cake.setName(orderType + "蛋糕 ");
  13. } else {
  14. System.out.println("暂不支持的蛋糕类型");
  15. return cake;
  16. }
  17. return cake;
  18. }
  19. }

实现预定方法

  1. /**
  2. * 预定方法实现类
  3. */
  4. public class OrderCake {
  5. public OrderCake(){
  6. setFactory();
  7. }
  8. private void setFactory() {
  9. String orderType;
  10. do {
  11. orderType = getType();
  12. //获取简单(静态)工厂
  13. AbstractCake cake = SimpleFactory.createCake(orderType);
  14. if(cake != null) {
  15. cake.prepare();
  16. cake.bake();
  17. cake.box();
  18. cake.send();
  19. } else {
  20. System.out.println("预定失败");
  21. break;
  22. }
  23. }while(true);
  24. }
  25. //输入蛋糕类型
  26. private String getType() {
  27. try {
  28. BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
  29. System.out.println("请输入蛋糕类型:");
  30. String str = strin.readLine();
  31. return str;
  32. } catch (IOException e) {
  33. e.printStackTrace();
  34. return "";
  35. }
  36. }
  37. }

由上代码可知:此时上新一个新品蛋糕,只需新增一个新品蛋糕类,修改SimpleFactory工厂类一处即可实现需求调整。

新需求:如果此时需要生产同一类型的蛋糕不同口味,如:奶油蛋糕的中国口味,奶油蛋糕的美国口味。
实现方式一:细化蛋糕类,新增一种口味蛋糕当做一个新品蛋糕(即把原来的奶油蛋糕类细化成不同口味的奶油蛋糕)
实现方式二:复制多份简单工厂,如一个中国简单工厂,一个美国简单工厂

方式一、二可以实现,但考虑到项目规模,可维护性和可扩展性来说,不是一个很好的方案。有没有什么好的方式可以很好的解决这个问题?==》工厂方法模式

框架或项目源码分析

JDK中的Calendar类使用的是简单工厂模式

  1. public static Calendar getInstance()
  2. {
  3. return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
  4. }
  5. private static Calendar createCalendar(TimeZone zone, Locale aLocale)
  6. {
  7. CalendarProvider provider =
  8. LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale)
  9. .getCalendarProvider();
  10. if (provider != null) {
  11. try {
  12. return provider.getInstance(zone, aLocale);
  13. } catch (IllegalArgumentException iae) {
  14. // fall back to the default instantiation
  15. }
  16. }
  17. Calendar cal = null;
  18. if (aLocale.hasExtensions()) {
  19. String caltype = aLocale.getUnicodeLocaleType("ca");
  20. if (caltype != null) {
  21. switch (caltype) {
  22. case "buddhist":
  23. cal = new BuddhistCalendar(zone, aLocale);
  24. break;
  25. case "japanese":
  26. cal = new JapaneseImperialCalendar(zone, aLocale);
  27. break;
  28. case "gregory":
  29. cal = new GregorianCalendar(zone, aLocale);
  30. break;
  31. }
  32. }
  33. }
  34. if (cal == null) {
  35. // If no known calendar type is explicitly specified,
  36. // perform the traditional way to create a Calendar:
  37. // create a BuddhistCalendar for th_TH locale,
  38. // a JapaneseImperialCalendar for ja_JP_JP locale, or
  39. // a GregorianCalendar for any other locales.
  40. // NOTE: The language, country and variant strings are interned.
  41. if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {
  42. cal = new BuddhistCalendar(zone, aLocale);
  43. } else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"
  44. && aLocale.getCountry() == "JP") {
  45. cal = new JapaneseImperialCalendar(zone, aLocale);
  46. } else {
  47. cal = new GregorianCalendar(zone, aLocale);
  48. }
  49. }
  50. return cal;
  51. }


应用场景

对于产品种类相对较少的情况,考虑使用简单工厂模式。使用简单工厂模式的客户端只需要传入工厂类的参数,不需要关心如何创建对象的逻辑,可以很方便地创建所需产品。