上文我们提到了简单工厂模式,但是简单工厂也会存在一些问题,具体出现哪些问题可以看这里,所以我们这里就用工厂方法模式来从新修改下代码
工厂方法模式介绍
工厂方法模式,又称工厂模式、多态工厂模式和虚拟构造器模式,定义一个用于创建对象的接口,但是让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类。与简单工厂模式相比,工厂方法模式最重要的特点是引入了抽象工厂角色,抽象工厂可以是接口,也可以是抽象类或者具体类。
还是先提一个需求
披萨需求 :订阅披萨(新增一个PapperPizza)
1.披萨有很多种类(GreekPizza,CheesePizza,PapperPizza)等
3.披萨的制作方式 prepare(准备原材料),bake(烘焙),cut(切割),box(装盒)
4.完成披萨订购功能
工厂方法模式思路:
我们可以考虑下吧工厂进行抽象画让其子类去实现具体的操作,比如我们创建一个抽象类的里面有个抽象方法createPizza(),在创建两个GreekPizzFactory和CheesePizzFactory去继承抽象类来实现创建披萨的逻辑,这样就算在增加一个产品我们只需要对应的增加一个工厂而不需要去修改代码
修改后的披萨抽象类及其子类
package com.zjh.designmodel.factory.methodfactory.entiy;
/**
* @Author: zjh
* @Description: 披萨需求(新增一个披萨产品)
* 1.披萨有很多种类(MethodGreekPizza,MethodCheesePizza,PapperPizza)等
* 2.披萨的制作方式 prepare(准备原材料),bake(烘焙),cut(切割),box(装盒)
* 3.完成披萨订购功能
* @Date: Created in 2020/4/28 14:14
* Modified by:
*/
public abstract class PizzaAbstract {
protected String name;
public void setName(String name) {
this.name = name;
}
public abstract void prepare();
public void bake() {
System.out.println(name+"披萨已经烘焙好了");
}
public void cut() {
System.out.println(name+"披萨已经切割完成");
}
public void box() {
System.out.println(name+"披萨已经装盒了");
}
}
package com.zjh.designmodel.factory.methodfactory.entiy;
/**
* @Author: zjh
* @Description:
* @Date: Created in 2020/5/6 19:24
* Modified by:
*/
public class CheesePizza extends PizzaAbstract {
@Override
public void prepare() {
System.out.println("CheesePizz披萨原材料准备好了");
this.name="CheesePizz";
}
}
package com.zjh.designmodel.factory.methodfactory.entiy;
/**
* @Author: zjh
* @Description:
* @Date: Created in 2020/5/6 19:22
* Modified by:
*/
public class GreekPizza extends PizzaAbstract {
@Override
public void prepare() {
System.out.println("GreekPizz披萨原材料准备好了");
this.name="GreekPizz";
}
}
package com.zjh.designmodel.factory.methodfactory.entiy;
/**
* @Author: zjh
* @Description:
* @Date: Created in 2020/5/11 20:14
* Modified by:
*/
public class PapperPizza extends PizzaAbstract {
@Override
public void prepare() {
System.out.println("胡椒披萨原材料准备好了");
this.name="Papper";
}
}
抽象工厂类和及其子类
package com.zjh.designmodel.factory.methodfactory;
import com.zjh.designmodel.factory.methodfactory.entiy.PizzaAbstract;
/**
* @Author: zjh
* @Description:
* @Date: Created in 2020/5/11 20:09
* Modified by:
*/
public interface PizzaFactory {
PizzaAbstract createPizza();
}
package com.zjh.designmodel.factory.methodfactory;
import com.zjh.designmodel.factory.methodfactory.entiy.CheesePizza;
import com.zjh.designmodel.factory.methodfactory.entiy.PizzaAbstract;
/**
* @Author: zjh
* @Description:
* @Date: Created in 2020/5/11 20:12
* Modified by:
*/
public class CheesePizzaImpl implements PizzaFactory {
@Override
public PizzaAbstract createPizza() {
return new CheesePizza();
}
}
package com.zjh.designmodel.factory.methodfactory;
import com.zjh.designmodel.factory.methodfactory.entiy.GreekPizza;
import com.zjh.designmodel.factory.methodfactory.entiy.PizzaAbstract;
/**
* @Author: zjh
* @Description:
* @Date: Created in 2020/5/11 20:13
* Modified by:
*/
public class GreekPizzalmpl implements PizzaFactory {
@Override
public PizzaAbstract createPizza() {
return new GreekPizza();
}
}
package com.zjh.designmodel.factory.methodfactory;
import com.zjh.designmodel.factory.methodfactory.entiy.PapperPizza;
import com.zjh.designmodel.factory.methodfactory.entiy.PizzaAbstract;
/**
* @Author: zjh
* @Description:
* @Date: Created in 2020/5/11 20:16
* Modified by:
*/
public class PapperPizzalmpl implements PizzaFactory {
@Override
public PizzaAbstract createPizza() {
return new PapperPizza();
}
}
订单类
package com.zjh.designmodel.factory.methodfactory.entiy;
import com.zjh.designmodel.factory.methodfactory.DrinkFactory;
import com.zjh.designmodel.factory.methodfactory.PizzaFactory;
/**
* @Author: zjh
* @Description: 订购Pizz
* @Date: Created in 2020/5/6 19:33
* Modified by:
*/
public class OrderPizza {
public OrderPizza(PizzaFactory pizzaFactory){
PizzaAbstract pizza = pizzaFactory.createPizza();
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}
}
测试
工厂方法模式的优点:
解决了同一个工厂下不满足opc原则的问题,当我们想在增加一个产品(Pizza)的时候我们只需要去创建对应的产品类和对应产品的工厂类不在需要去修改代码。工厂模式可以说是简单工厂模式的进一步抽象和拓展,在保留了简单工厂的封装优点的同时,让扩展变得简单,让继承变得可行,增加了多态性的体现
工厂方法模式的缺点:
虽然解决了opc(增加单一产品)的问题但是当我们增加很多产品的时候那么对应要增加2n个类,在一定程度上增加了系统的复杂度;并且如果我们想增加一个工厂怎么办(比如我想订饮料),会发现这时候必须要修改订单类这就相当于又违反了opc原则,这时候可以考虑下抽象工厂模式
JDK源码(List接口的iterator方法交给子类ArrayList实现)
总结
- 在工厂方法模式中定义一个用于创建对象的接口,但是让子类决定将哪一个类实化。工厂方法模式让一个类的实例化延迟到其子类,它是一种类创建型模式。
- 工厂方法模式包含抽象产品(MethodPizza)、具体产品(MethodGreekPizza)、抽象工厂(MethodAbstractFactory)和具体工厂(MethodGreekOrder)4个角色。其中,抽产品是定义产品的接口;具体产品实现了抽象产品接口,某种类型的具体产品由专门的具体工厂创建;抽象工厂声明了工厂方法,用于返回一个产品;具体工厂是抽象工厂类的子类,实现了在抽象工厂中声明的工厂方法,返回一个具体产品类的实例。
- 虽然解决了产品的opc的问题但是在一定程度上增加了系统的复杂度并且增加另一个种类工厂的时候还是会出现opc问题