简单工厂模式
先看一个具体的需求
- 有一个披萨项目:要便于披萨的扩展,要便于维护。
- 披萨的种类很多(比如:GreekPizza、CheesePizza)
- 披萨的制作有prepare(准备),bake(烘焙),cut(切块),box(装盒)
- 完成披萨店的订购功能
传统实现方式:
类图:
代码:
pizza类的代码:
public abstract class Pizza {
/**
* 准备原材料 不同的披萨不一样 做成抽象方法
*/
abstract void prepare();
public void bake() {
System.out.println(" baking");
}
public void cut() {
System.out.println(" cutting");
}
public void box() {
System.out.println(" boxing");
}
}
public class CheesePizza extends Pizza {
@Override
void prepare() {
System.out.println(" cheese pizza prepare");
}
}
public class GreekPizza extends Pizza {
@Override
void prepare() {
System.out.println("greek pizza prepare");
}
}
PizzaStore代码
public class PizzaStore {
public static void main(String[] args) {
PizzaStore pizzaStore = new PizzaStore();
pizzaStore.orderPizza("cheese");
pizzaStore.orderPizza("greek");
pizzaStore.orderPizza("pepper");
}
public Pizza orderPizza(String type) {
Pizza pizza = null;
if (type.equals("cheese")) {
pizza = new CheesePizza();
} else if (type.equals("greek")) {
pizza = new GreekPizza();
} else if (type.equals("pepper")) {
pizza = new PepperPizza();
}
if (pizza != null) {
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}
return null;
}
}
传统方式的优缺点 - 优点是比较好理解,简单易操作·
- 缺点是违反了设计模式的ocp原则,即外扩展开发,对修改关闭。即当我们给类增加新功能的时候,尽量不修改代码,或者尽量少修改代码。 我们要增加一个PepperPizza时,OrderPizza类需要做如下修改
if (type.equals("cheese")) {
pizza = new CheesePizza();
} else if (type.equals("greek")) {
pizza = new GreekPizza();
}else if(type.equals("pepper")){
pizza = new PepperPizza();
}
改进思路:将创建披萨对象移到orderPizza()之外,即将创建Pizza的代码移到另一个对象中,由这个新对象专职创建Pizza,这对象就称为工厂。
简单工厂类代码
public class PizzaSimpleFactory {
public static Pizza createPizza(String type) {
if (type.equals("cheese")) {
return new CheesePizza();
} else if (type.equals("greek")) {
return new GreekPizza();
} else if (type.equals("pepper")) {
return new PepperPizza();
}
return null;
}
}
改进后的PizzaStore
public class PizzaStore {
public static void main(String[] args) {
PizzaStore pizzaStore = new PizzaStore();
pizzaStore.orderPizza("cheese");
pizzaStore.orderPizza("greek");
pizzaStore.orderPizza("pepper");
}
public Pizza orderPizza(String type) {
Pizza pizza = PizzaSimpleFactory.createPizza(type);
if (pizza != null) {
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}
return null;
}
}
改进后的类图,改进前PizzaStore需要依赖具体的Pizza类型,改进后PizzaStore不用再依赖具体的pizza。
简单工厂其实不是一个设计模式,反而比较像是一种编程习惯。
工厂方法模式
- 扩展:每个地区披萨加盟店需要提供不同风味的披萨,比如纽约需要提供纽约风味披萨,芝加哥需要提供芝加哥风味披萨。 -思路1: 利用简单工厂,可以写出不同的工厂,分别是NYStylePizzaSimpleFactory,LDStylePizzaSimpleFactory等。能满足当前扩展的需要,但是考虑到项目规模,以及软件的可维护性、可扩展性并不是特别好。
- 思路2:使用工厂方法模式 工厂方法模式:定义了一个创建对象的接口,由子类来决定要实例化的类是哪一个,工厂方法让类把实例化推迟到子类。
public abstract class PizzaStore {
public Pizza orderPizza(String type) {
Pizza pizza = createPizza(type);
if (pizza != null) {
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}
return null;
}
public abstract Pizza createPizza(String type);
}
public class NYStylePizzaStore extends PizzaStore {
@Override
public Pizza createPizza(String type) {
if (type.equals("cheese")) {
return new NYCheesePizza();
} else if (type.equals("greek")) {
return new NYGreekPizza();
} else if (type.equals("pepper")) {
return new NYPepperPizza();
}
return null;
}
}
public class PizzaOrder {
public static void main(String[] args) {
PizzaStore nyStylePizzaStore = new NYStylePizzaStore();
nyStylePizzaStore.orderPizza("cheese");
PizzaStore ldStylePizzaStore = new LDStylePizzaStore();
ldStylePizzaStore.orderPizza("cheese");
}
}
抽象工厂模式
- 抽象工厂模式:定义了一个接口用于创建相关或有依赖关系的对象簇,而无需指明具体的类。
- 抽象工厂模式可以将简单工厂模式和工厂方法模式进行整合。
- 从设计层面看,抽象工厂模式就是对简单工厂模式的改进(或者进一步的抽象)。
- 将工厂抽象为两层,AbstractFactory和具体实现的工厂子类。我们可以根据创建对象类型使用对应的工厂子类。这样将单个的简单工厂变成了工厂簇,利于代码的维护和扩展。
/**
* 抽象工厂模式的抽象层
**/
public interface AbstractPizzaFactory {
Pizza createPizza(String type);
}
public class NYFactory implements AbstractPizzaFactory {
@Override
public Pizza createPizza(String type) {
if (type.equals("cheese")) {
return new NYCheesePizza();
} else if (type.equals("greek")) {
return new NYGreekPizza();
} else if (type.equals("pepper")) {
return new NYPepperPizza();
}
return null;
}
}
public class OrderPizza {
private AbstractPizzaFactory abstractPizzaFactory;
public OrderPizza(AbstractPizzaFactory abstractPizzaFactory) {
this.abstractPizzaFactory = abstractPizzaFactory;
}
public Pizza orderPizza(String type) {
Pizza pizza = abstractPizzaFactory.createPizza(type);
if (pizza != null) {
pizza.bake();
pizza.cut();
pizza.box();
}
return pizza;
}
}
public class PizzaStore {
public static void main(String[] args) {
new OrderPizza(new NYFactory()).orderPizza("cheese");
new OrderPizza(new LDFactory()).orderPizza("cheese");
}
}
工厂模式在JDK中的应用
public class FactoryTest {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
String dateInfo = String.format("%d-%d-%d %d:%d:%d", calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH)+1, calendar.get(Calendar.DAY_OF_MONTH),
calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE),
calendar.get(Calendar.SECOND));
System.out.println(dateInfo);
}
}
Calendar类的创建使用了工厂模式,具体可参加JDK源码