原理或定義
简单工厂模式:是由一个工厂对象决定创建出哪一种产品类的实例。是最简单实用的模式。
工厂方法模式:在工厂方法模式中,核心的工厂类不再负责所有的产品的创建,而是将具体创建的工作交给子类去做。该核心类成为一个抽象工厂角色,仅负责给出具体工厂子类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节。
抽象工厂模式:为创建一组相关或相互依赖的对象提供一个接口,无需指定他们的具体类。
類圖
簡單工廠類圖
工廠方法類圖
抽象工廠類圖
案例与代码
本模式以披萨项目作为案例
披萨项目:要方便披萨品种的扩展、要便于维护、要能运行时扩展
一般披萨族设计:
披萨基类/接口:
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 CheesePizza extends Pizza { @Override public void prepare() { // TODO Auto-generated method stub super.setname("CheesePizza"); System.out.println(name+" preparing;"); } } public class ChinesePizza extends Pizza { @Override public void prepare() { // TODO Auto-generated method stub super.setname("ChinesePizza"); System.out.println(name+" preparing;"); } } public class GreekPizza extends Pizza { @Override public void prepare() { // TODO Auto-generated method stub super.setname("GreekPizza"); System.out.println(name+" preparing;"); } }
点餐类:
public class OrderPizza { public OrderPizza() { Pizza pizza = null; String ordertype; do { ordertype = gettype(); if (ordertype.equals("cheese")) { pizza = new CheesePizza(); } else if (ordertype.equals("greek")) { pizza = new GreekPizza(); } else if (ordertype.equals("pepper")) { pizza = new PepperPizza(); } else if (ordertype.equals("chinese")) { pizza = new ChinesePizza(); } 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 type:"); String str = strin.readLine(); return str; } catch (IOException e) { e.printStackTrace(); return ""; } } }
public class PizzaStroe { public static void main(String[] args) { OrderPizza mOrderPizza; mOrderPizza=new OrderPizza(); } }
简单工厂模式的设计方案:
披萨基类和子类不变。
工厂类:
public class SimplePizzaFactory { public Pizza CreatePizza(String ordertype) { Pizza pizza = null; if (ordertype.equals("cheese")) { pizza = new CheesePizza(); } else if (ordertype.equals("greek")) { pizza = new GreekPizza(); } else if (ordertype.equals("pepper")) { pizza = new PepperPizza(); } return pizza; } }
点餐类:
public class OrderPizza { SimplePizzaFactory mSimplePizzaFactory; public OrderPizza(SimplePizzaFactory mSimplePizzaFactory) { setFactory(mSimplePizzaFactory); } public void setFactory(SimplePizzaFactory mSimplePizzaFactory) { Pizza pizza = null; String ordertype; this.mSimplePizzaFactory = mSimplePizzaFactory; do { ordertype = gettype(); pizza = mSimplePizzaFactory.CreatePizza(ordertype); if (pizza != null) { 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 type:"); String str = strin.readLine(); return str; } catch (IOException e) { e.printStackTrace(); return ""; } } }
public class PizzaStroe { public static void main(String[] args) { SimplePizzaFactory mSimplePizzaFactory; OrderPizza mOrderPizza; mOrderPizza=new OrderPizza(new SimplePizzaFactory()); } }
简单工厂模式定义了一个创建对象的类,由这个类来封装实例化对象的行为,方便披萨品种的扩展、便于维护、能运行时扩展。
披萨项目新需求的困惑:披萨项目加盟店
不同加盟店的地域不一样,生产的披萨会根据地域调整口味或造型,也就是一个种类的披萨在不同的地域会生产出不同的披萨。
增加披萨子类:
public class LDCheesePizza extends Pizza { @Override public void prepare() { // TODO Auto-generated method stub super.setname("LDCheesePizza"); System.out.println(name+" preparing;"); } } public class LDPepperPizza extends Pizza { @Override public void prepare() { // TODO Auto-generated method stub super.setname("LDPepperPizza"); System.out.println(name+" preparing;"); } }
public class NYCheesePizza extends Pizza { @Override public void prepare() { // TODO Auto-generated method stub super.setname("NYCheesePizza"); System.out.println(name+" preparing;"); } } public class NYPepperPizza extends Pizza { @Override public void prepare() { // TODO Auto-generated method stub super.setname("NYPepperPizza"); System.out.println(name+" preparing;"); } }
工厂方法模式设计方案:
点餐基类:
public abstract class OrderPizza { public OrderPizza() { Pizza pizza = null; String ordertype; do { ordertype = gettype(); pizza = createPizza(ordertype); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); } while (true); } abstract Pizza createPizza(String ordertype); private String gettype() { try { BufferedReader strin = new BufferedReader(new InputStreamReader( System.in)); System.out.println("input pizza type:"); String str = strin.readLine(); return str; } catch (IOException e) { e.printStackTrace(); return ""; } } }
点餐子类/实现类:public class LDOrderPizza extends OrderPizza { @Override Pizza createPizza(String ordertype) { Pizza pizza = null; if (ordertype.equals("cheese")) { pizza = new LDCheesePizza(); } else if (ordertype.equals("pepper")) { pizza = new LDPepperPizza(); } return pizza; } }
public class NYOrderPizza extends OrderPizza { @Override Pizza createPizza(String ordertype) { Pizza pizza = null; if (ordertype.equals("cheese")) { pizza = new NYCheesePizza(); } else if (ordertype.equals("pepper")) { pizza = new NYPepperPizza(); } return pizza; } }
管理/测试类:
public class PizzaStroe { public static void main(String[] args) { OrderPizza mOrderPizza; mOrderPizza=new NYOrderPizza(); } }
定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例化推迟到子类
抽象工厂的设计方案:披萨基类和子类不变。
工厂基类/接口:
public interface AbsFactory { public Pizza CreatePizza(String ordertype) ; }
工厂实现类:
public class LDFactory implements AbsFactory { @Override public Pizza CreatePizza(String ordertype) { Pizza pizza = null; if (ordertype.equals("cheese")) { pizza = new LDCheesePizza(); } else if (ordertype.equals("pepper")) { pizza = new LDPepperPizza(); } return pizza; } }
public class NYFactory implements AbsFactory { @Override public Pizza CreatePizza(String ordertype) { Pizza pizza = null; if (ordertype.equals("cheese")) { pizza = new NYCheesePizza(); } else if (ordertype.equals("pepper")) { pizza = new NYPepperPizza(); } return pizza; } }
点餐类:public class OrderPizza { AbsFactory mFactory; public OrderPizza(AbsFactory mFactory) { setFactory(mFactory); } public void setFactory(AbsFactory mFactory) { Pizza pizza = null; String ordertype; this.mFactory = mFactory; do { ordertype = gettype(); pizza = mFactory.CreatePizza(ordertype); if (pizza != null) { 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 type:"); String str = strin.readLine(); return str; } catch (IOException e) { e.printStackTrace(); return ""; } } }
管理 / 测试类:public class PizzaStroe { public static void main(String[] args) { OrderPizza mOrderPizza; mOrderPizza=new OrderPizza(new LDFactory()); } }
抽象工厂定义了一个接口用于创建相关或有依赖关系的对象族,而无需明确指定具体类
依赖抽象原则
变量不要持有具体类的引用
不要让类继承自具体类,要继承自抽象类或接口
不要覆盖基类中已实现的方法
不同形式的關聯
工厂方法模式是简单工厂模式的衍生,解决了许多简单工厂模式的问题。首先完全实现‘开-闭 原则’,实现了可扩展。其次更复杂的层次结构,可以应用于产品结果复杂的场合。
抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。
使用場景
1、 如果一个对象拥有很多子类,那么创建该对象的子类使用工厂模式是最合适的,不但可以面向接口的编程,为维护以及开发带来方便。
2、如果创建某个对象时需要进行许多额外的操作,如查询数据库然后将查询到的值赋予要创建的对象(单例初始化时使用比较多),或是需要许多额外的赋值等等
優缺點
简单工厂的主要优点有:
1、简单工厂模式能够根据外界给定的信息,决定究竟应该创建哪个具体类的对象。明确区分了各自的职责和权力,有利于整个软件体系结构的优化。
简单工厂的缺点主要有:
很明显工厂类集中了所有实例的创建逻辑,容易违反GRASPR的高内聚的责任分配原则。
工厂方法的主要优点有:
1. 子类提供挂钩。基类为工厂方法提供缺省实现,子类可以重写新的实现,也可以继承父类的实现。--加一层间接性,增加了灵活性
2. 屏蔽产品类。产品类的实现如何变化,调用者都不需要关心,只需关心产品的接口,只要接口保持不变,系3. 统中的上层模块就不会发生变化。
4. 典型的解耦框架。高层模块只需要知道产品的抽象类,其他的实现类都不需要关心,符合迪米特法则,符合依赖倒置原则,符合里氏替换原则。
5. 多态性:客户代码可以做到与特定应用无关,适用于任何实体类。
工厂方法的缺点主要有:
需要Creator和相应的子类作为factory method的载体,如果应用模型确实需要creator和子类存在,则很好;否则的话,需要增加一个类层次。
抽象工厂的主要优点有:
1. 抽象工厂模式隔离了具体类的生产,使得客户并不需要知道什么被创建。
2. 当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
3. 增加新的具体工厂和产品族很方便,无须修改已有系统,符合“开闭原则”。
抽象工厂的缺点主要有:
增加新的产品等级结构很复杂,需要修改抽象工厂和所有的具体工厂类,对“开闭原则”的支持呈现倾斜性。