1.工厂方法模式
接着简单工厂模式,我们来看工厂方法模式。
先看一个新的需求:披萨项目有了新的需求,客户在下单披萨时可以选择下单不同地区不同口味的pizza,比如北京的奶酪pizza,伦敦的胡椒pizza等。
我们可以像前面简单工厂模式一样,分别创建多个不同地区的简单工厂类。比如BJPizzaSimpleFactory,LDPizzaSimpleFactory等。但是这样在实际开发中软件的可维护性和可扩展性并不好。
因此,我们可以采用工厂方法模式。
工厂方法模式介绍:
将pizza对象的实例化功能抽象为抽象方法,在不同口味的点餐子类中实现,由子类决定要实例化的类。工厂方法模式将对象的实例化推迟到子类。
pizza抽象类:
package factory.factorymethod.pizzastore.pizza;
/**
* @Author Worm
* @Date 2020/8/10 10:02
* @Version 1.0
**/
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;
}
}
一个pizza子类的例子,实际上有多个。
package factory.factorymethod.pizzastore.pizza;
/**
* @Author Worm
* @Date 2020/8/10 14:43
* @Version 1.0
**/
public class BJCheesePizza extends Pizza {
@Override
public void prepare() {
setName("北京奶酪pizza");
System.out.println("北京奶酪pizza准备原材料");
}
}
OrderPizza类里实现一个抽象方法,由具体的子类去实现。
package factory.factorymethod.pizzastore.order;
import factory.factorymethod.pizzastore.pizza.Pizza;
import factory.simplefactory.pizzastore.order.SimpleFactory;
import factory.simplefactory.pizzastore.pizza.CheesePizza;
import factory.simplefactory.pizzastore.pizza.GreekPizza;
import factory.simplefactory.pizzastore.pizza.PepperPizza;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* @Author Worm
* @Date 2020/8/10 10:08
* @Version 1.0
**/
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);
}
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 "";
}
}
//定义一个抽象方法,让各个工厂子类自己实现
abstract Pizza createPizza(String orderType);
}
不同的OrderPizza子类:
package factory.factorymethod.pizzastore.order;
import factory.factorymethod.pizzastore.pizza.BJCheesePizza;
import factory.factorymethod.pizzastore.pizza.BJPepperPizza;
import factory.factorymethod.pizzastore.pizza.Pizza;
/**
* @Author Worm
* @Date 2020/8/10 14:55
* @Version 1.0
**/
public class BJOrderPizza extends OrderPizza {
@Override
Pizza createPizza(String orderType) {
Pizza pizza = null;
if (orderType.equals("cheese")) {
pizza = new BJCheesePizza();
} else if (orderType.equals("pepper")) {
pizza = new BJPepperPizza();
}
return pizza;
}
}
package factory.factorymethod.pizzastore.order;
import factory.factorymethod.pizzastore.pizza.*;
/**
* @Author Worm
* @Date 2020/8/10 14:55
* @Version 1.0
**/
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;
}
}
客户端:
package factory.factorymethod.pizzastore.order;
/**
* @Author Worm
* @Date 2020/8/10 15:00
* @Version 1.0
**/
public class PizzaStore {
public static void main(String[] args) {
//创建北京口味的各种pizza
// new BJOrderPizza();
new LDOrderPizza();
}
}
2.抽象工厂模式
同样的,与工厂方法模式类似,我们也可以采用抽象工厂模式。
抽象工厂模式:是对简单工厂模式的进一步改进和抽象。它将工厂抽象为两层,ABSFactory(抽象工厂)和具体的工厂子类,程序员可以根据项目创建对应的工厂子类,将单个的简单工厂变为工厂簇。
pizza基类及其子类与前面相同。
抽象工厂接口:
package factory.absfactory.pizzastore.order;
import factory.absfactory.pizzastore.pizza.Pizza;
/**
* @Author Worm
* @Date 2020/8/10 15:35
* @Version 1.0
**/
//一个抽象工厂模式的抽象层
public interface ABSFactory {
Pizza createPizza(String orderType);
}
各个工厂子类:
package factory.absfactory.pizzastore.order;
import factory.absfactory.pizzastore.pizza.BJCheesePizza;
import factory.absfactory.pizzastore.pizza.BJPepperPizza;
import factory.absfactory.pizzastore.pizza.Pizza;
/**
* @Author Worm
* @Date 2020/8/10 15:36
* @Version 1.0
**/
public class BJFactory implements ABSFactory {
@Override
public Pizza createPizza(String orderType) {
Pizza pizza = null;
if (orderType.equals("cheese")) {
pizza = new BJCheesePizza();
} else if (orderType.equals("pepper")) {
pizza = new BJPepperPizza();
}
return pizza;
}
}
package factory.absfactory.pizzastore.order;
import factory.absfactory.pizzastore.pizza.*;
/**
* @Author Worm
* @Date 2020/8/10 15:36
* @Version 1.0
**/
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;
}
}
OrderPizza:
package factory.absfactory.pizzastore.order;
import factory.absfactory.pizzastore.pizza.Pizza;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* @Author Worm
* @Date 2020/8/10 15:44
* @Version 1.0
**/
public class OrderPizza {
ABSFactory absFactory;
public OrderPizza(ABSFactory absFactory) {
setFactory(absFactory);
}
private void setFactory(ABSFactory factory) {
System.out.println("使用抽象工厂模式");
Pizza pizza = null;
String orderType = "";
absFactory = factory;
do {
orderType = gettype();
//这里根据需要传入的可能会是不同的工厂子类
pizza = absFactory.createPizza(orderType);
if (pizza != null) {
pizza.prepare();
pizza.bake();
pizza.box();
pizza.cut();
} else {
System.out.println("订购失败");
break;
}
} 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 "";
}
}
}
客户端:
package factory.absfactory.pizzastore.order;
/**
* @Author Worm
* @Date 2020/8/10 15:58
* @Version 1.0
**/
public class PizzaStore {
public static void main(String[] args) {
// new OrderPizza(new BJFactory());
new OrderPizza(new LDFactory());
}
}
3.源码分析
工厂模式在JDK-Calendar中的应用
Calendar cal = Calendar.getInstance();
进入createCalendar方法
运用了简单工厂模式
4.工厂模式总结
工厂模式的意义在于将实例化的代码提取出来,放到一个类中统一管理维护,使之与主项目解耦,提高项目的扩展性和维护性。
工厂模式有三种实现形式:简单工厂模式,工厂方法模式,抽象工厂模式。
遵循了设计模式的依赖抽象原则:
创建对象实例时不直接new而是将该动作放在一个工厂的方法中并返回(也称之为变量不要直接持有具体类的引用)。
不要让类继承具体类,而要继承抽象类或实现接口。
以及不要覆盖基类中以实现的方法。