为什么使用工厂模式
软件开发没有银弹,一种设计思路好,必然有道理。这里讲下工厂模式,工厂模式属于创建型设计模式。
比如你有一家披萨店,可以造出各种各样的披萨,另外有客户订购披萨。这样就可以使用工厂模式来创建披萨。
简单工厂
在实际项目中使用最多的是简单工厂,而且一般业务问题也比较好抽象成简单工厂的方式, 经常把获取类的方法做成静态的,也称为静态工厂。
UML图:
Tips:
其中Pizza类可以做成一个抽象类,当然做成接口也可以,然后让对应的子类去实现。
基类/抽象类/接口代码实现
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;
}
}
具体实现类客户端举例代码实现
public class CheesePizza extends Pizza{
@Override
public void prepare() {
System.out.println("给制作奶酪Pizza准备原材料");
}
}
简单工厂类实现
public class SimpleFactory {
public Pizza createPizza(String orderType) {
Pizza pizza = null;
if (Objects.equals("greek", orderType)) {
pizza = new GreekPizza();
pizza.setName("greek");
} else if (Objects.equals("cheese", orderType)) {
pizza = new CheesePizza();
pizza.setName("cheese");
}
return pizza;
}
}
客户端调用
public class OrderPizza {
public static void main(String[] args) {
//TODO: 一般情况下这里是用依赖注入
SimpleFactory simpleFactory = new SimpleFactory();
Pizza pizza = simpleFactory.createPizza("greek");
//通过prepare判断披萨类型
pizza.prepare();
pizza.bake();
}
}
Tips:
在上述的简单工厂类的实现中,是用的if/else来得到不同的Pizza具体子类,在实际的工程项目中,比如Spring框架,可以用HashMap的方式,把对应的type和实际子类映射起来。
但是需要注意一点,需要使用@PostConstruct注解进行HashMap的初始化。
或者使用static语句块进行初始化
工厂方法
在上面那个订购披萨的场景中,原先只是奶酪, 胡椒披萨,这样可以用简单工厂模式解决。如果现在需求变了, 增加了地域的维度,比如北京的奶酪披萨,伦敦的胡椒披萨,这个时候也可以用简单工厂,比如北京的披萨简单工厂,伦敦的披萨简单工厂,但是这个不是最优实践。
推荐使用工厂方法,将对象的实例化过程推迟到子类去完成,子类共同继承一个创建类的抽象方法。
UML图:
抽象工厂
抽象工厂可以看做是简单工厂和工厂方法的结合,前面说到工厂方法将create()方法变成抽象方法,让子类去实现。这样还是有一点不是完全面向接口编程,所以抽象工厂直接使用一个抽象工厂接口去给子工厂去实现。这样由简单工厂变成了一系列工厂簇。
UML图: