一个小例子引入 具体需要:一个披萨项目,要便于披萨种类的扩展,要便于维护
披萨的种类有很多(比如GreekPizz,CheesePizz等)
披萨的制作有prepare,bake,cut,box
完成披萨店订购功能设计模式之工厂模式(factory pattern) 传统方式 这是pizza对应的类和类图public abstract class pizza { protected String name; public abstract void prepare () ; public void bake () { System.out.println(name + " baking;" ); } public void cut () { System.out.println(name + " cutting;" ); } public void box () { System.out.println(name + " boxing;" ); } public void setName (String name) { this .name = name; } } public class PepperPizza extends pizza { @Override public void prepare () { System.out.println(" 给PepperPizza准备原材料 " ); } } public class GreekPizza extends pizza { @Override public void prepare () { System.out.println(" 给希腊披萨准备原材料 " ); } } public class CheesePizza extends pizza { @Override public void prepare () { System.out.println(" 给制作奶酪披萨 准备原材料 " ); } }
用于进行披萨订购public class OrderPizza { public OrderPizza () { pizza pizza = null ; String orderType; do { orderType = getType(); if (orderType.equals("greek" )) { pizza = new GreekPizza(); pizza.setName(" 希腊披萨 " ); } else if (orderType.equals("cheese" )) { pizza = new CheesePizza(); pizza.setName(" 奶酪披萨 " ); } else if (orderType.equals("pepper" )) { pizza = new PepperPizza(); pizza.setName("胡椒披萨" ); } else { break ; } pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); } while (true ); } private String getType () { try { BufferedReader strin = new BufferedReader(new InputStreamReader(System.in)); System.out.println("input pizza 种类:" ); String str = strin.readLine(); return str; } catch (IOException e) { e.printStackTrace(); return "" ; } } } public class PizzaStore { public static void main (String[] args) { new OrderPizza(); } }
如果没有设计模式,我们采取的方案应该就会使这样的,从uml可以直观的看出来,我们如果想要再增加一种pizza,那么对整个应用的改动是很大的。 因为OrderPizza会有很多种,这里OrderPizza相当于一个门店,不同的门店需求不同卖的东西不同会产生OrderPizza1,OrderPizza2,OrderPizza3等等,如果直接与pizza类依赖这样会非常混乱传统方式的优缺点
优点是比较好理解,简单易操作
缺点是违反了设计原则的ocp原则,即对扩展开放,对修改关闭。即当我们给类增加新功能的时候尽量不修改代码,或者尽可能少的修改代码
改进思路 把创建pizza对象封装到一个类中,这样我们有新的pizza种类的时候,只需要修改该类就可以,其他有创建到pizza对象的代码不需要修改—简单工厂模式
简单工厂模式 基本介绍
简单工厂模式属于创建型模式,是工厂模式的一种。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例 。简单工厂模式是工厂模式家族中最简单实用的模式
简单工厂模式:定义一个创建对象的类,由这个类来封装实例化对象的行为
再软件开发中,当我们会用到大量的创建某种、某类或者某批对象时,就会使用到工厂模式
类图
代码实现 创建简单工厂
public class SimpleFactory { public pizza createPizza (String orderType) { pizza pizza = null ; System.out.println("使用简单工厂模式" ); if (orderType.equals("greek" )) { pizza = new GreekPizza(); pizza.setName(" 希腊披萨 " ); } else if (orderType.equals("cheese" )) { pizza = new CheesePizza(); pizza.setName(" 奶酪披萨 " ); } else if (orderType.equals("pepper" )) { pizza = new PepperPizza(); pizza.setName("胡椒披萨" ); } return pizza; } }
修改orderpizza类和PizzaStore类
public class OrderPizza { private SimpleFactory simpleFactory; private pizza pizza = null ; public OrderPizza (SimpleFactory simpleFactory) { setFactory(simpleFactory); } private void setFactory (SimpleFactory simpleFactory) { String orderType = "" ; this .simpleFactory = simpleFactory; do { orderType = getType(); pizza = this .simpleFactory.createPizza(orderType); if (pizza != null ) { pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); } else { System.out.println(" 订购披萨失败 " ); break ; } }while (true ); } private String getType () { try { BufferedReader strin = new BufferedReader(new InputStreamReader(System.in)); System.out.println("input pizza 种类:" ); String str = strin.readLine(); return str; } catch (IOException e) { e.printStackTrace(); return "" ; } } } public class PizzaStore { public static void main (String[] args) { new OrderPizza(new SimpleFactory()); } }
这样简单工厂模式就是实现了,这样的好处是做到了OrderPizza与pizza的解耦,如果我们再创建一个pizza或者再创建一个orderpizza的时候改动的只有要添加的类和工厂。 简单工厂模式也叫做静态工厂模式,我们还可以这样修改代码实现工厂模式 修改简单工厂类
public static Pizza createPizza2 (String orderType) { pizza pizza = null ; System.out.println("使用静态简单工厂模式" ); if (orderType.equals("greek" )) { pizza = new GreekPizza(); pizza.setName(" 希腊披萨 " ); } else if (orderType.equals("cheese" )) { pizza = new CheesePizza(); pizza.setName(" 奶酪披萨 " ); } else if (orderType.equals("pepper" )) { pizza = new PepperPizza(); pizza.setName("胡椒披萨" ); } return pizza; }
修改orderpizza类和pizzastore类
public class OrderPizza2 { Pizza pizza = null ; String orderType = "" ; public OrderPizza2 () { do { orderType = getType(); pizza = SimpleFactory.createPizza2(orderType); if (pizza != null ) { pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); } else { System.out.println(" 订购披萨失败 " ); break ; } } while (true ); } private String getType () { try { BufferedReader strin = new BufferedReader(new InputStreamReader(System.in)); System.out.println("input pizza 种类:" ); String str = strin.readLine(); return str; } catch (IOException e) { e.printStackTrace(); return "" ; } } } public class PizzaStore { public static void main (String[] args) { new OrderPizza2(); } }
使用静态工厂更加方便。
工厂方法模式
现在有一个新的需求:客户在点餐的时候可以点不同口味的披萨,比如北京的奶酪pizza,北京的胡椒pizza等等等,也就是说客户不仅仅要pizza那么简单还要要pizza的制作方式
思路1:使用简单工厂模式,创建不同的产品,针对每一种可能性,这这样对以后的扩展和系统的维护都非常复杂
思路2:使用工厂方法模式
基本介绍
简单工厂模式设计方案 :将披萨项目的实例化功能抽象成抽象方法,在不同的口味点餐字类中具体实现
工厂方法模式:定义一个创建对象的抽象方法,由字类决定要实例化的类,工厂方法模式将对象的实例化推迟到了子类 工厂方法模式结构图
类图
代码实现 Pizza类
public abstract class Pizza { protected String name; public abstract void prepare () ; public void bake () { System.out.println(name + " baking;" ); } public void cut () { System.out.println(name + " cutting;" ); } public void box () { System.out.println(name + " boxing;" ); } public void setName (String name) { this .name = name; } } public class BJCheessPizzea extends Pizza { @Override public void prepare () { setName("北京的奶酪披萨" ); System.out.println("北京的奶酪披萨 准备备原材料" ); } } public class BJPepperPizza extends Pizza { @Override public void prepare () { setName("北京的胡椒披萨" ); System.out.println("北京的胡椒披萨 准备备原材料" ); } } public class LDCheessPizzea extends Pizza { @Override public void prepare () { setName("伦敦的奶酪披萨" ); System.out.println("伦敦的奶酪披萨 准备备原材料" ); } } public class LDPepperPizza extends Pizza { @Override public void prepare () { setName("伦敦的胡椒披萨" ); System.out.println("伦敦的胡椒披萨 准备备原材料" ); } }
OrderPizza类
public abstract class OrderPizza { abstract Pizza createPizza (String orderType) ; } public class LDOrderPizza extends OrderPizza { @Override Pizza createPizza (String orderType) { Pizza pizza = null ; if (orderType.equals("cheese" )) { pizza = new LDCheessPizzea(); } else if (orderType.equals("pepper" )) { pizza = new LDPepperPizza(); } return pizza; } } public class BJOrderPizza extends OrderPizza { @Override Pizza createPizza (String orderType) { Pizza pizza = null ; if (orderType.equals("cheese" )) { pizza = new BJCheessPizzea(); } else if (orderType.equals("pepper" )) { pizza = new BJPepperPizza(); } return pizza; } }
使用
public class PizzaStore { public static void main (String[] args) { OrderPizza orderPizza = new BJOrderPizza(); Pizza pizza = orderPizza.createPizza("cheese" ); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); } }
这样就实现了工厂方法模式
抽象工厂 基本介绍
抽象工厂模式:定义了一个interface用于创建相关或有依赖关系的对象簇,而无需指明具体对象
抽象工厂模式可以将简单工厂模式和工厂方法模式进行整合
从设计层面看,抽象工厂模式就是对简单工厂模式的改进,或者说是进一步的抽象
将工厂抽象成两层,AbsFactory(抽象工厂)和具体实现的工厂子类。程序员可以根据创建对象类型使用对应的工厂子类,这样将单个的简单工厂类变成工厂簇,更利于代码的维护和扩展抽象工厂结构图
类图
抽象工厂主要对应多个产品簇来说的,抽象工厂可以实现多个产品簇之间关系
代码实现 首先我们定义pizza接口以及实现类
public abstract class Pizza { protected String name; public abstract void prepare () ; public void bake () { System.out.println(name + " baking;" ); } public void cut () { System.out.println(name + " cutting;" ); } public void box () { System.out.println(name + " boxing;" ); } public void setName (String name) { this .name = name; } } public class PepperPizza extends Pizza { @Override public void prepare () { setName("伦敦的胡椒披萨" ); System.out.println("伦敦的胡椒披萨 准备备原材料" ); } } public class CheessPizzea extends Pizza { @Override public void prepare () { setName("伦敦的奶酪披萨" ); System.out.println("伦敦的奶酪披萨 准备备原材料" ); } }
创建饮料类
public abstract class Drinks { public abstract void prepare () ; public void make () { System.out.println("制作" ); } } public class cola extends Drinks { @Override public void prepare () { System.out.println("准备可乐原材料" ); } } public class fruitjuice extends Drinks { @Override public void prepare () { System.out.println("准备果汁原材料" ); } }
创建工厂来实例化这几个类
public interface AbsFactory { public Pizza createPizza () ; public Drinks CreateDrinks () ; } public class Meal1Factory implements AbsFactory { @Override public Pizza createPizza () { CheessPizzea cheessPizzea = new CheessPizzea(); return cheessPizzea; } @Override public Drinks CreateDrinks () { cola c = new cola(); return c; } } public class Meal2Factory implements AbsFactory { @Override public Pizza createPizza () { PepperPizza pepperPizza = new PepperPizza(); return pepperPizza; } @Override public Drinks CreateDrinks () { fruitjuice f = new fruitjuice(); return f; } }
调用
public class orderpizza { public static void main (String[] args) { AbsFactory factory = new Meal1Factory(); Drinks drinks = factory.CreateDrinks(); Pizza cheese = factory.createPizza(); drinks.make(); cheese.prepare(); } }
关于抽象工厂的好处建议看一下大话设计模式 ,讲的非常透彻
小结 个人对于简单工厂,工厂方法模式,抽象工厂的理解是
简单工厂主要是为了将创建对象统一起来,方便管理
工厂方法模式:是对一种抽象产品进行实例化
抽象工厂:是为了实例化不同种产品,将调用与实现解耦,两者之间不过多牵扯。