【案例】 点单披萨项目(披萨种类,制作过程,订购),实现点单功能
Pizza类
1 //将Pizza 类做成抽象 2 public abstract class Pizza { 3 protected String name; //名字 4 //准备原材料, 不同的披萨不一样,因此,我们做成抽象方法 5 public abstract void prepare(); 6 public void bake() { 7 System.out.println(name + " baking;"); 8 } 9 public void cut() { 10 System.out.println(name + " cutting;"); 11 } 12 //打包 13 public void box() { 14 System.out.println(name + " boxing;"); 15 } 16 public void setName(String name) { 17 this.name = name; 18 } 19 }
点单功能类
1 public class OrderPizza { 2 //构造器 3 public OrderPizza() { 4 Pizza pizza = null; 5 String orderType; // 订购披萨的类型 6 do { 7 orderType = getType(); 8 if (orderType.equals("greek")) { 9 pizza = new GreekPizza(); 10 pizza.setName(" 希腊披萨 "); 11 } else if (orderType.equals("cheese")) { 12 pizza = new CheesePizza(); 13 pizza.setName(" 奶酪披萨 "); 14 } else if (orderType.equals("pepper")) { 15 pizza = new PepperPizza(); 16 pizza.setName("胡椒披萨"); 17 } else { 18 break; 19 } 20 //输出pizza 制作过程 21 pizza.prepare(); 22 pizza.bake(); 23 pizza.cut(); 24 pizza.box(); 25 26 } while (true); 27 } 28 }
弊端:违反ocp原则,即对拓展开放,对修改关闭。当我们增加功能时,尽量不修改代码绘者少修改。而OrderPizza类中当增加一种Pizza字类时,则需要修改所有OrderPizza类(OrderPizza只是一个代称,可能有很多跟此功能一样的类)中对Pizza种类判断的代码。
1.简单工厂模式
简单工厂模式属于创建型模式,是工厂模式的一种。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式定义了一个创建对象的类,由这个类来封装实例化对象的行为。在软件开发中,当我们会用到大量的创建某种、某类对象时,就会使用到工厂模式。
把创建Pizza对象封装到一个类中,这样我们有新的Pizza种类的时候,只需要修改此类即可,其他创建Pizza对象的代码就不需要修改了。
1 //简单工厂类 2 public class SimpleFactory { 3 4 //更加orderType 返回对应的Pizza 对象 5 public Pizza createPizza(String orderType) { 6 7 Pizza pizza = null; 8 9 System.out.println("使用简单工厂模式"); 10 if (orderType.equals("greek")) { 11 pizza = new GreekPizza(); 12 pizza.setName(" 希腊披萨 "); 13 } else if (orderType.equals("cheese")) { 14 pizza = new CheesePizza(); 15 pizza.setName(" 奶酪披萨 "); 16 } else if (orderType.equals("pepper")) { 17 pizza = new PepperPizza(); 18 pizza.setName("胡椒披萨"); 19 } 20 21 return pizza; 22 } 23 24 }
1 public class OrderPizza { 2 //定义一个简单工厂对象 3 SimpleFactory simpleFactory; 4 Pizza pizza = null; 5 6 //构造器 7 public OrderPizza(SimpleFactory simpleFactory) { 8 setFactory(simpleFactory); 9 } 10 11 public void setFactory(SimpleFactory simpleFactory) { 12 String orderType = ""; //用户输入的 13 14 this.simpleFactory = simpleFactory; //设置简单工厂对象 15 16 do { 17 orderType = getType(); 18 pizza = this.simpleFactory.createPizza(orderType); 19 20 //输出pizza 21 if(pizza != null) { //订购成功 22 pizza.prepare(); 23 pizza.bake(); 24 pizza.cut(); 25 pizza.box(); 26 } else { 27 System.out.println(" 订购披萨失败 "); 28 break; 29 } 30 }while(true); 31 } 32 33 // 写一个方法,可以获取客户希望订购的披萨种类 34 private String getType() { 35 try { 36 BufferedReader strin = new BufferedReader(new InputStreamReader(System.in)); 37 System.out.println("input pizza 种类:"); 38 String str = strin.readLine(); 39 return str; 40 } catch (IOException e) { 41 e.printStackTrace(); 42 return ""; 43 } 44 }
1 //相当于一个客户端,发出订购 2 public class PizzaStore { 3 public static void main(String[] args) { 4 //使用简单工厂模式 5 new OrderPizza(new SimpleFactory()); 6 System.out.println("~~退出程序~~"); 7 } 8 9 }
2.工厂方法模式
【新需求】每种Pizza有不同口味,客户可以点单可以选择不同的口味。这是可以使用创建不同的简单工厂类生产不同的口味,但是维护性和拓展性不好。此时可使用工厂方法模式。将披萨项目的实例化功能抽象成抽象方法,在不同口味点餐子类中具体实现。
工厂方法模式:定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例化推迟到子类。
1 public abstract class OrderPizza { 2 3 //定义一个抽象方法,createPizza , 让各个工厂子类自己实现 4 abstract Pizza createPizza(String orderType); 5 6 // 构造器 7 public OrderPizza() { 8 Pizza pizza = null; 9 String orderType; // 订购披萨的类型 10 do { 11 orderType = getType(); 12 pizza = createPizza(orderType); //抽象方法,由工厂子类完成 13 //输出pizza 制作过程 14 pizza.prepare(); 15 pizza.bake(); 16 pizza.cut(); 17 pizza.box(); 18 19 } while (true); 20 } 21 22 // 写一个方法,可以获取客户希望订购的披萨种类 23 private String getType() { 24 try { 25 BufferedReader strin = new BufferedReader(new InputStreamReader(System.in)); 26 System.out.println("input pizza 种类:"); 27 String str = strin.readLine(); 28 return str; 29 } catch (IOException e) { 30 e.printStackTrace(); 31 return ""; 32 } 33 } 34 }
1 public class BJOrderPizza extends OrderPizza { 2 3 @Override 4 Pizza createPizza(String orderType) { 5 6 Pizza pizza = null; 7 if(orderType.equals("cheese")) { 8 pizza = new BJCheesePizza(); 9 } else if (orderType.equals("pepper")) { 10 pizza = new BJPepperPizza(); 11 } 12 // TODO Auto-generated method stub 13 return pizza; 14 } 15 }
1 public class LDOrderPizza extends OrderPizza { 2 @Override 3 Pizza createPizza(String orderType) { 4 5 Pizza pizza = null; 6 if(orderType.equals("cheese")) { 7 pizza = new LDCheesePizza(); 8 } else if (orderType.equals("pepper")) { 9 pizza = new LDPepperPizza(); 10 } 11 // TODO Auto-generated method stub 12 return pizza; 13 } 14 }
3.抽象工厂模式
抽象工厂模式定义了一个interface用于创建相关或有依赖关系的对象簇,而无需指明具体的类。
抽象工厂模式可以将简单工厂模式和工厂方法模式整合,从设计层面上看,抽象工厂模式就是简单工厂模式的进一步抽象。将工厂抽象成两层:AbsFactory抽象工厂和具体实现的工厂类。程序员可以根据创建对象类型使用对应的工厂子类。这样就将简单的工厂类变成了工厂簇,利于维护扩展。
1 //一个抽象工厂模式的抽象层(接口) 2 public interface AbsFactory { 3 //让下面的工厂子类来 具体实现 4 public Pizza createPizza(String orderType); 5 }
1 public class LDFactory implements AbsFactory { 2 @Override 3 public Pizza createPizza(String orderType) { 4 System.out.println("~使用的是抽象工厂模式~"); 5 Pizza pizza = null; 6 if (orderType.equals("cheese")) { 7 pizza = new LDCheesePizza(); 8 } else if (orderType.equals("pepper")) { 9 pizza = new LDPepperPizza(); 10 } 11 return pizza; 12 } 13 }
1 //这是工厂子类 2 public class BJFactory implements AbsFactory { 3 @Override 4 public Pizza createPizza(String orderType) { 5 System.out.println("~使用的是抽象工厂模式~"); 6 // TODO Auto-generated method stub 7 Pizza pizza = null; 8 if(orderType.equals("cheese")) { 9 pizza = new BJCheesePizza(); 10 } else if (orderType.equals("pepper")){ 11 pizza = new BJPepperPizza(); 12 } 13 return pizza; 14 } 15 }
1 public class OrderPizza { 2 AbsFactory factory; 3 // 构造器 4 public OrderPizza(AbsFactory factory) { 5 setFactory(factory); 6 } 7 8 private void setFactory(AbsFactory factory) { 9 Pizza pizza = null; 10 String orderType = ""; // 用户输入 11 this.factory = factory; 12 do { 13 orderType = getType(); 14 // factory 可能是北京的工厂子类,也可能是伦敦的工厂子类 15 pizza = factory.createPizza(orderType); 16 if (pizza != null) { // 订购ok 17 pizza.prepare(); 18 pizza.bake(); 19 pizza.cut(); 20 pizza.box(); 21 } else { 22 System.out.println("订购失败"); 23 break; 24 } 25 } while (true); 26 } 27 28 // 写一个方法,可以获取客户希望订购的披萨种类 29 private String getType() { 30 try { 31 BufferedReader strin = new BufferedReader(new InputStreamReader(System.in)); 32 System.out.println("input pizza 种类:"); 33 String str = strin.readLine(); 34 return str; 35 } catch (IOException e) { 36 e.printStackTrace(); 37 return ""; 38 } 39 } 40 }
1 public class PizzaStore { 2 public static void main(String[] args) { 3 // TODO Auto-generated method stub 4 //new OrderPizza(new BJFactory()); 5 new OrderPizza(new LDFactory()); 6 } 7 }
4.小结
工厂模式意义:将实例化对象的代码提取出来,放到一个类中统一管理和维护,达到和主项目的依赖关系的解耦。从而提高项目的扩展性和维护性。
Tips:创建对象实例不要直接new类,而是把这个new动作放入一个工厂的方法中,并返回,即变量不要持有具体类的引用。
不要让类直接继承具体类,而是继承抽象类或实现接口。
不要覆盖类中已经实现的方法。