1. 简单工厂
代码类图
java代码
// 定义pizza类型
public enum PizzaType {
cheese,clam
}
// 披萨父类
public class Pizza {
public String type;
public Pizza(PizzaType type) {
this.type = type.name();
}
public void bake() {
System.out.println(type + " pizza is baking");
}
public void cut() {
System.out.println(type + " pizza is cutting");
}
public void box() {
System.out.println(type + " pizza is boxing");
}
}
// 芝士披萨
public class CheesePizza extends Pizza {
public CheesePizza(PizzaType type) {
super(type);
}
@Override
public void bake() {
System.out.println("special " + type + " pizza is baking");
}
}
// 蛤蜊披萨
public class ClamPizza extends Pizza {
public ClamPizza(PizzaType type) {
super(type);
}
@Override
public void cut() {
System.out.println("special " + type + " pizza is cutting");
}
}
// 简单披萨工厂
public class PizzaFactory {
public Pizza createPizza(PizzaType type) {
if (PizzaType.cheese.equals(type)) {
return new CheesePizza(type);
} else if (PizzaType.clam.equals(type)) {
return new ClamPizza(type);
} else {
throw new NullPointerException("pizza type is not exist");
}
}
}
// 披萨店
public class PizzaStore {
private PizzaFactory pizzaFactory = new PizzaFactory();
public Pizza orderPizza(PizzaType type) {
Pizza pizza = pizzaFactory.createPizza(type);
pizza.bake();
pizza.cut();
pizza.box();
System.out.println("--- finish ---");
return pizza;
}
}
// 测试类
public class Test {
public static void main(String[] args) {
new Test().test();
}
void test() {
PizzaStore pizzaStore = new PizzaStore();
pizzaStore.orderPizza(PizzaType.cheese);
pizzaStore.orderPizza(PizzaType.clam);
}
}
注:
- 简单工厂其实不是一个设计模式,反而比较像一种编程习惯。由于经常使用,有些开发人员把这种编程习惯误认为是“工厂模式”。
- PizzaFactory被提取出来后可以被其他类使用。
2. 工厂方法模式
工厂方法模式 定义了一个创建对象的接口,但由子类来决定要实例化的实例是哪一个。工厂方法让类把实例化推迟到子类。
代码类图
java代码
// 披萨类型
public enum PizzaType {
cheese,clam
}
// 披萨父类
public class Pizza {
public String type;
public Pizza(PizzaType type) {
this.type = type.name();
}
public void bake() {
System.out.println(type + " pizza is baking");
}
public void cut() {
System.out.println(type + " pizza is cutting");
}
public void box() {
System.out.println(type + " pizza is boxing");
}
}
// 芝加哥风味的芝士披萨
public class CCStyleCheesePizza extends Pizza {
public CCStyleCheesePizza(PizzaType type) {
super(type);
}
@Override
public void cut() {
System.out.println("special " + type + " pizza(Chicago) is cutting");
}
}
// 芝加哥风味的蛤蜊披萨
public class CCStyleClamPizza extends Pizza {
public CCStyleClamPizza(PizzaType type) {
super(type);
}
@Override
public void bake() {
System.out.println("special " + type + " pizza(Chicago) pizza is baking");
}
}
// 纽约风味的披萨
public class NYStyleCheesePizza extends Pizza {
public NYStyleCheesePizza(PizzaType type) {
super(type);
}
@Override
public void bake() {
System.out.println("special " + type + " pizza(New York) is baking");
}
}
// 纽约风味的蛤蜊披萨
public class NYStyleClamPizza extends Pizza {
public NYStyleClamPizza(PizzaType type) {
super(type);
}
@Override
public void box() {
System.out.println("special " + type + " pizza(New York) pizza is boxing");
}
}
// 披萨店父类
public abstract class PizzaStore {
public abstract Pizza create(PizzaType type);
public Pizza orderPizza(PizzaType type) {
Pizza pizza = create(type);
pizza.bake();
pizza.cut();
pizza.box();
System.out.println("--- finish ---");
return pizza;
}
}
// 芝加哥披萨店
public class CCPizzaStore extends PizzaStore {
@Override
public Pizza create(PizzaType type) {
if (PizzaType.cheese.equals(type)) {
return new CCStyleCheesePizza(type);
} else if (PizzaType.clam.equals(type)) {
return new CCStyleClamPizza(type);
} else {
throw new NullPointerException("pizza type is not exist");
}
}
}
// 纽约披萨店
public class NYPizzaStore extends PizzaStore {
@Override
public Pizza create(PizzaType type) {
if (PizzaType.cheese.equals(type)) {
return new NYStyleCheesePizza(type);
} else if (PizzaType.clam.equals(type)) {
return new NYStyleClamPizza(type);
} else {
throw new NullPointerException("pizza type is not exist");
}
}
}
// 测试类
public class Test {
public static void main(String[] args) {
new Test().test();
}
void test() {
PizzaStore nyPizzaStore = new NYPizzaStore();
PizzaStore ccPizzaStore = new CCPizzaStore();
nyPizzaStore.orderPizza(PizzaType.cheese);
nyPizzaStore.orderPizza(PizzaType.clam);
ccPizzaStore.orderPizza(PizzaType.cheese);
ccPizzaStore.orderPizza(PizzaType.clam);
}
}
注:
- 现在你可以方便的添加一个ChinaPizzaFactory(需要继承PizzaFactory),也可以很方便的添加各种奇怪的披萨(需要继承Pizza)
- 将创建对象的代码集中在一个对象或者方法中,可以避免代码重复,方便以后维护
- 客户端在实例化对象时,只会依赖于接口,而不是具体类
- 针对接口编程,而不针对实现编程
- 让代码更具有弹性,可以应对未来的发展
抽象工厂模式
抽象工厂模式提供一个接口,由于创建相关或依赖对象的家族,而不需要明确指定的具体类。
代码类图
java代码
// CCStyleCheesePizza, CCStyleClamPizza, NYStyleCheesePizza, NYStyleClamPizza, Pizza, PizzaType 六个类与工厂方法中的一样,这里不再贴出代码
// 披萨工厂接口
public interface PizzaFactory {
Pizza createCheesePizza();
Pizza createClamPizza();
}
// 芝加哥披萨工厂
public class CCPizzaFactory implements PizzaFactory {
@Override
public Pizza createCheesePizza() {
return new CCStyleCheesePizza(PizzaType.cheese);
}
@Override
public Pizza createClamPizza() {
return new CCStyleClamPizza(PizzaType.clam);
}
}
// 纽约披萨工厂
public class NYPizzaFactory implements PizzaFactory {
@Override
public Pizza createCheesePizza() {
return new NYStyleCheesePizza(PizzaType.cheese);
}
@Override
public Pizza createClamPizza() {
return new NYStyleClamPizza(PizzaType.clam);
}
}
// 披萨店父类
public class PizzaStore {
public Pizza orderPizza(Pizza pizza) {
pizza.bake();
pizza.cut();
pizza.box();
System.out.println("--- finish ---");
return pizza;
}
}
// 测试类
public class Test {
public static void main(String[] args) {
new Test().test();
}
void test() {
PizzaFactory nyPizzaFactory = new NYPizzaFactory();
PizzaFactory ccPizzaFactory = new CCPizzaFactory();
PizzaStore pizzaStore = new PizzaStore();
pizzaStore.orderPizza(nyPizzaFactory.createCheesePizza());
pizzaStore.orderPizza(nyPizzaFactory.createClamPizza());
pizzaStore.orderPizza(ccPizzaFactory.createCheesePizza());
pizzaStore.orderPizza(ccPizzaFactory.createClamPizza());
}
}
注
- 抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要关心实际产出来的具体产品是什么
- 客户从具体的产品中解耦
- 你可以很方便的添加其他工厂
对比工厂方法和抽象工厂
- 工厂方法:继承,不确定将来要实现哪些类。如NYPizzaStore方便的加入新类型的Pizza。
- 抽象工厂:组合,必须知道创建集合的所有对象类型,但是对象的实现我们并不关系。如:示例中,我们必须要知道所有的pizza种类,如果新加了一种,需要改变所有实现接口的类,具体创建的对象是什么样的,不同的工厂可以有不同的实现,NYPizzaFactory有纽约风味的pizza,其他工厂有其他工厂的披萨,只要是Pizza的子类。
- 总结:抽象工厂类似于多个只创建一个对象的工厂方法的组合。例如,现在工厂方法中NYPizzaStore的create方法不再接受参数,并且只创建一个对象,修改后的create方法就类似于抽象工厂中NYPizzaFactory的其中一个方法。所以抽象工厂的方法经常以工厂方法的方式来实现。
参考文章
1. Head First 设计模式