1.简单工厂模式 基本介绍
简单工厂模式是属于创建型模式,是工厂模式的一种。简单工厂模式是由工厂对象决定创建出哪一种产品类的实例。
简单工厂模式:定义了一个创建对象的类,由这个类来封装实例化对象的行为 (代码)
在软件开发中,当我们会用到大量创建某类,或某批对象时,就会使用到工厂模式。
示例:看一个披萨的项目:要便于披萨种类的扩展,要便于维护。
披萨的种类很多(比如GreekPizza、CheesePizza等)
披萨的制作有prepare,bake,cut,box等
完成披萨店订购功能。
传统方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 abstract class Pizza { protected String name; public abstract void prepare () ; public void bake () { System.out.println(name + "bake" ); } public void cut () { System.out.println(name + "cut" ); } public void box () { System.out.println(name + "box" ); } public void setName (String name) { this .name = name; } } class CheesePizza extends Pizza { @Override public void prepare () { System.out.println("准备奶酪pizza原材料" ); } } class GreekPizza extends Pizza { @Override public void prepare () { System.out.println("准备希腊pizza原材料" ); } } class OrderPizza { public OrderPizza () { Pizza pizza = null ; String orderPizzaType; do { orderPizzaType = getType(); if (orderPizzaType.equals("greek" )){ pizza = new GreekPizza(); pizza.setName("希腊披萨" ); }else if (orderPizzaType.equals("cheese" )){ pizza = new CheesePizza(); pizza.setName("奶酪披萨" ); } else { break ; } pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); }while (true ); } private String getType () { Scanner scanner = new Scanner(System.in); System.out.println("请输入pizza类型" ); String type = scanner.next(); return type; } } class PizzaStore { public static void main (String[] args) throws ParseException { new OrderPizza(); } }
传统方式优缺点:
好理解,简单易操作。
缺点是违反了设计模式开闭原则,即对扩展性(提供方)开放,对(使用方)修改关闭
比如这时我们要增加一个Pizza的种类(Pepper披萨),我们要新增PepperPizza类,修改OrderPizza类的代码。
改进思路:把创建Pizza对象封装到一个类中,这样我们有了新的Pizza种类时,只需要修改类就可以,其他有创建Pizza对象的代码就不用修改了。->简单工厂模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 abstract class Pizza{ protected String name; //准备原材料,每种pizza原材料不一样 public abstract void prepare(); public void bake(){ System.out.println(name + "bake"); } public void cut(){ System.out.println(name + "cut"); } public void box(){ System.out.println(name + "box"); } public void setName(String name) { this.name = name; } } class CheesePizza extends Pizza{ @Override public void prepare() { System.out.println("准备奶酪pizza原材料"); } } class GreekPizza extends Pizza{ @Override public void prepare() { System.out.println("准备希腊pizza原材料"); } } class OrderPizza{ private SimpleFactory simpleFactory; private Pizza pizza; public OrderPizza(SimpleFactory simpleFactory) { setSimpleFactory(simpleFactory); } public void setSimpleFactory(SimpleFactory simpleFactory) { String pizzaType = ""; this.simpleFactory = simpleFactory; do { pizzaType = getType(); pizza = simpleFactory.createPizza(pizzaType); if (pizzaType != null){ //输出pizza制作流程 pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); }else { System.out.println("订购pizza失败"); break; } }while (true); } private String getType() { Scanner scanner = new Scanner(System.in); System.out.println("请输入pizza类型"); String type = scanner.next(); return type; } } class SimpleFactory{ public Pizza createPizza(String orderPizzaType){ Pizza pizza = null; if (orderPizzaType.equals("greek")){ pizza = new GreekPizza(); pizza.setName("希腊披萨"); }else if (orderPizzaType.equals("cheese")){ pizza = new CheesePizza(); pizza.setName("奶酪披萨"); } return pizza; } } class PizzaStore{ public static void main(String[] args) throws ParseException { new OrderPizza(); } }
第二种写法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 class SimpleFactory { public static Pizza createPizza (String orderPizzaType) { Pizza pizza = null ; if (orderPizzaType.equals("greek" )){ pizza = new GreekPizza(); pizza.setName("希腊披萨" ); }else if (orderPizzaType.equals("cheese" )){ pizza = new CheesePizza(); pizza.setName("奶酪披萨" ); } return pizza; } } class OrderPizza { private Pizza pizza; public OrderPizza () { String pizzaType = "" ; do { pizzaType = getType(); pizza = SimpleFactory.createPizza(pizzaType); if (pizzaType != null ){ pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); }else { System.out.println("订购pizza失败" ); break ; } }while (true ); } private String getType () { Scanner scanner = new Scanner(System.in); System.out.println("请输入pizza类型" ); String type = scanner.next(); return type; } }
2.工厂方法模式 看一个新需求:
客户在点披萨时,可以点不同口味的披萨,比如北京的奶酪pizza,北京的胡椒pizza,伦敦的胡椒pizza。
思路1:
使用简单工厂模式,创建不同的简单工厂类,比如BJPizzaSimpleFactory、LDPizzaSimpleFactory等等。但考虑到项目规模,以及软件的可维护性、可扩展性并不是特别好。
思路2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 abstract class Pizza { protected String name; public abstract void prepare () ; public void bake () { System.out.println(name + "bake" ); } public void cut () { System.out.println(name + "cut" ); } public void box () { System.out.println(name + "box" ); } public void setName (String name) { this .name = name; } } class BJCheesePizza extends Pizza { @Override public void prepare () { System.out.println("准备奶酪pizza原材料" ); } } class BJGreekPizza extends Pizza { @Override public void prepare () { System.out.println("准备BJ希腊pizza原材料" ); } } abstract class OrderPizza { public OrderPizza () { Pizza pizza; String pizzaType = "" ; do { pizzaType = getType(); pizza = createPizza(pizzaType); if (pizzaType != null ){ pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); }else { System.out.println("订购pizza失败" ); break ; } }while (true ); } protected abstract Pizza createPizza (String pizzaType) ; private String getType () { Scanner scanner = new Scanner(System.in); System.out.println("请输入pizza类型" ); String type = scanner.next(); return type; } } class BJOrderPizza extends OrderPizza { @Override protected Pizza createPizza (String pizzaType) { Pizza pizza = null ; if (pizzaType.equals("greek" )){ pizza = new BJGreekPizza(); }else if (pizzaType.equals("cheesePizza" )){ pizza = new BJCheesePizza(); } return pizza; } }
3.抽象工厂模式 基本介绍
定义了一个interface用于创建相关或有依赖关系的对象簇,而无需指明具体的类。
抽象工厂模式可以将简单工厂模式和工厂方法模式进行整合
从设计层面看,抽象工厂模式就是对简单工厂模式的改进(或称为进一步的抽象)。
将工厂抽象为两层,AbsFactory(抽象工厂)和具体实现的工厂子类。程序员可以根据创建对象类型使用对应的工厂子类。这样将简单的工厂类变成了工厂簇,更利于代码的维护和扩展。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 abstract class Pizza { protected String name; public abstract void prepare () ; public void bake () { System.out.println(name + "bake" ); } public void cut () { System.out.println(name + "cut" ); } public void box () { System.out.println(name + "box" ); } public void setName (String name) { this .name = name; } } class BJCheesePizza extends Pizza { @Override public void prepare () { System.out.println("准备奶酪pizza原材料" ); } } class BJGreekPizza extends Pizza { @Override public void prepare () { System.out.println("准备BJ希腊pizza原材料" ); } } interface AbsFactory { Pizza createPizza (String pizzaType) ; } class OrderPizza { private AbsFactory absFactory; public void setAbsFactory (AbsFactory absFactory) { this .absFactory = absFactory; Pizza pizza; String pizzaType = "" ; do { pizzaType = getType(); pizza = absFactory.createPizza(pizzaType); if (pizzaType != null ){ pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); }else { System.out.println("订购pizza失败" ); break ; } }while (true ); } private String getType () { Scanner scanner = new Scanner(System.in); System.out.println("请输入pizza类型" ); String type = scanner.next(); return type; } } class BJFactory implements AbsFactory { @Override public Pizza createPizza (String pizzaType) { Pizza pizza = null ; if (pizzaType.equals("greek" )){ pizza = new BJGreekPizza(); pizza.setName("BJGreekPizza" ); }else if (pizzaType.equals("cheese" )){ pizza = new BJCheesePizza(); pizza.setName("BJCheesePizza" ); } return pizza; } } class PizzaStore { public static void main (String[] args) throws ParseException { OrderPizza orderPizza = new OrderPizza(); orderPizza.setAbsFactory(new BJFactory()); } }
小结
工厂模式的意义
将实例化对象的代码提取出来,放到一个类中统一管理和维护,达到和主项目的依赖关系的解耦。从而提高项目的扩展性和可维护性。