演进顺序:传统写法 —>简单工厂—>工厂方法—>抽象工厂

需求案例:

制作蛋糕
1.准备
2.烘焙
3.包装
4.配送

传统写法


类图:

image.png

  1. 定义抽象类
  2. 实现类继承抽象类
  3. 预定方法
  4. 客户端测试
  5. 分析

定义抽象类

  1. /**
  2. * 蛋糕抽象类
  3. */
  4. public abstract class AbstractCake {
  5. protected String name;
  6. public abstract void prepare();
  7. public void bake() {
  8. System.out.println(name + "烘焙;");
  9. }
  10. public void box() {
  11. System.out.println(name + "包装;");
  12. }
  13. public void send() {
  14. System.out.println(name + "配送;");
  15. }
  16. public void setName(String name) {
  17. this.name = name;
  18. }
  19. }

实现类继承抽象类

  1. /**
  2. * 奶油蛋糕
  3. */
  4. public class CreamCake extends AbstractCake{
  5. @Override
  6. public void prepare() {
  7. System.out.println("原料:原胚、奶油");
  8. }
  9. }
  1. /**
  2. * 水果蛋糕
  3. */
  4. public class fruitCake extends AbstractCake{
  5. @Override
  6. public void prepare() {
  7. System.out.println("原料:原胚、水果");
  8. }
  9. }

预定方法

  1. /**
  2. * 预定方法
  3. */
  4. public class OrderCake {
  5. public OrderCake() {
  6. AbstractCake cake;
  7. String orderType;
  8. do {
  9. orderType = getType();
  10. if (orderType.equals("水果")) {
  11. cake = new fruitCake(); // ===>耦合
  12. cake.setName(orderType+"蛋糕 ");
  13. } else if (orderType.equals("奶油")) {
  14. cake = new CreamCake(); // ===>耦合
  15. cake.setName(orderType+"蛋糕 ");
  16. } else {
  17. System.out.println("暂不支持的蛋糕类型");
  18. break;
  19. }
  20. //操作流程
  21. cake.prepare();
  22. cake.bake();
  23. cake.box();
  24. cake.send();
  25. } while (true);
  26. }
  27. //输入蛋糕类型
  28. private String getType() {
  29. try {
  30. BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
  31. System.out.println("请输入蛋糕类型:");
  32. String str = strin.readLine();
  33. return str;
  34. } catch (IOException e) {
  35. e.printStackTrace();
  36. return "";
  37. }
  38. }
  39. }

客户端测试

  1. /**
  2. * 客户端测试
  3. */
  4. public class CakeStore {
  5. public static void main(String[] args) {
  6. new OrderCake();
  7. }
  8. }
  9. //测试结果
  10. 请输入蛋糕类型:
  11. 水果
  12. 原料:原胚、水果
  13. 水果蛋糕 烘焙;
  14. 水果蛋糕 包装;
  15. 水果蛋糕 配送;
  16. 请输入蛋糕类型:
  17. 巧克力
  18. 暂不支持的蛋糕类型

分析:
如上代码可以看到:预定方法OrderCake在方法中直接new对应的实现类,此时上新新蛋糕类型,如:巧克力蛋糕,如果有orderCake1~n,则需要修改多个OrderCake方法,这违反了开闭原则。有没有什么好的方式只修改一处就可以实现全局修改呢?将创建对象依托给工厂去创建 ==》简单工厂模式