工厂方法模式
我们先来看一个需求:客户在点披萨时,可以点不同口味的披萨,比如河南的奶酪pizza、河南的胡椒pizza或者是伦敦的奶酪pizza、伦敦的胡椒pizza。
思路
思路1:使用简单工厂模式,创建不同的简单工厂类,比如HNPizzaSimpleFactory、
LDPizzaSimpleFactory等等,从当前这个案例来说,也是可以的,但是考虑到项目的规模,以及软件的可维护性、可扩展性并不是特别好
思路2:使用工厂方法模式
工厂方法模式介绍
工厂方法模式设计方案:将披萨项目的实例化功能抽象成抽象方法,在不同的口味点餐子类中具体实现。
工厂方法模式:定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例化推迟到子类。
类图
我们简单工厂模式是直接在工厂创建了对象实例,而工厂方法模式是将创建对象的权限交给了他的子类,HNOrderPizz(河南披萨)和LNOrderPizza(伦敦披萨)
代码
Pizza实体类
/**
* @author 王庆华
* @version 1.0
* @date 2020/12/21 20:06
* @Description TODO
* @pojectname 披萨抽象类 设置为抽象类
*/
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;
}
}
河南披萨和伦敦披萨的4个子类
/**
* @author 王庆华
* @version 1.0
* @date 2020/12/25 20:47
* @Description TODO
* @pojectname 河南奶酪代码
*/
public class HNCheesePizza extends Pizza{
@Override
public void prepare() {
setName("河南的奶酪披萨");
System.out.println("给河南奶酪披萨准备原材料");
}
}
/**
* @author 王庆华
* @version 1.0
* @date 2020/12/25 20:49
* @Description TODO
* @pojectname 河南胡椒代码
*/
public class HNPepperPizza extends Pizza {
@Override
public void prepare() {
setName("河南的胡椒披萨");
System.out.println("给河南胡椒披萨准备原材料");
}
}
/**
* @author 王庆华
* @version 1.0
* @date 2020/12/25 20:47
* @Description TODO
* @pojectname 伦敦奶酪代码
*/
public class LDCheesePizza extends Pizza{
@Override
public void prepare() {
setName("伦敦的奶酪披萨");
System.out.println("给伦敦奶酪披萨准备原材料");
}
}
伦敦胡椒披萨也如此
OrderPizza订单代码
/**
* @author 王庆华
* @version 1.0
* @date 2020/12/21 20:14
* @Description TODO
* @pojectname 订购披萨代码
*/
public abstract class OrderPizza {
//定义一个抽象方法createPizza,让各个工厂子类自己实现
abstract Pizza createPizza(String orderType);
//构造器
public OrderPizza(){
Pizza pizza = null;
String orderType ;//orderType用户输入pizza类型
do {
orderType = getType();//获取用户订购的pizza类型
System.out.println(orderType);
pizza = createPizza(orderType);//抽象方法,实际上又工厂子类完成
//输出制作pizza信息
//订购成功
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 "";
}
}
}
OrderPizza的两个子类
/**
* @author 王庆华
* @version 1.0
* @date 2020/12/25 20:56
* @Description TODO
* @pojectname 河南披萨订单代码
*/
public class HNOrderPizza extends OrderPizza {
@Override
Pizza createPizza(String orderType) {
Pizza pizza = null;
if (orderType.equals("cheese")) {
pizza = new HNCheesePizza();
}else if (orderType.equals("pepper")){
pizza = new HNPepperPizza();
}
return pizza;
}
}
/**
* @author 王庆华
* @version 1.0
* @date 2020/12/25 20:56
* @Description TODO
* @pojectname 伦敦披萨代码
*/
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 PizzaStore {
public static void main(String[] args) {
//创建河南口味的各种方法
new HNOrderPizza();
}
}
根据我们new的种类,我们就能得到不同的结果
input pizza 种类:
cheese
cheese
给河南奶酪披萨准备原材料
河南的奶酪披萨baking;
河南的奶酪披萨cutting;
河南的奶酪披萨boxing
input pizza 种类:
pepper
那我们要是 new LDOrderPizza();
那么输出的都是有关伦敦披萨的口味
总结
我们再来总结一下,在我们的简单工厂模式中,我们的思路是,直接让我们的OrderPizza订单类,根据不同的orderType口味,来new一个不同口味的pizza,而我们的方法工厂模式是这样的:我们的方法工厂模式,将我们的OrderPizza订单类写成了一个含有createPiiza()抽象方法的抽象类,这个抽象方法是用来创建披萨的实例对象的,但是他是抽象方法,所以我们的河南披萨订单和伦敦披萨订单要继承主类OrderPizza这个类,也就是说,我们把创建实例对象的任务分发给了不同的子类,子类本来就不同,他们自然也就能制作不同地方的口味披萨,然后子类创建完不同地方的不同口味的披萨再返回给我们的OrderPizza主类,再由我们的这个主类输出相应的信息