工厂方法
定义
定义一个用于创建对象的接口,让子类决定实例化哪一个类。使得一个类的实例化延迟到子类。
在工厂方法模式中,存在以下角色:
- 抽象产品(Product)角色。定义了一个产品的接口,用于声明其公共方法。
- 具体产品(ConcreteProduct)角色。实现了抽象产品接口,每个具体产品都有自己特定的实现。
- 抽象工厂(AbstractFactory)角色。定义了一个用于创建产品的接口,这个接口包含一个或多个用于创建具体产品实例的方法。
- 具体工厂(ConcreteFactory)角色。实现了抽象工厂接口,负责创建具体的产品实例。
创建一个创建对象的工厂,我们很容易能想到下面这个简单的示例,即根据类型去创建一个匹配的对象。
public class SimpleFactory {
public static Product getInstance(String type) {
switch (type) {
case "0": return new Apple();
case "1": return new Huawei();
default: return null;
}
}
}
虽然这个简单工厂方法简单实用,但是随着业务不停的发展,type类型越来越多,并且我们可能还要处理一些其他逻辑来满足业务需求,case代码也将不停地增长。
此时,引入工厂方法就是绝佳的选择
- 定义抽象工厂
Product是一个接口即抽象产品,定义了method()方法,getInstance()即由子类决定创建哪一个类的对象
public abstract class AbstractFactory {
Product getProduct() {
return getInstance();
}
public abstract Product getInstance();
}
- 定义具体工厂
Huawei和Apple即具体产品
public class HuaweiFactory extends AbstractFactory {
@Override
public Product getInstance() {
return new Huawei();
}
}
public class AppleFactory extends AbstractFactory {
@Override
public Product getInstance() {
return new Apple();
}
}
显然,作为设计模式的一种,必然有优点。
- 易拓展:不需要修改存量代码就能很好的拓展业务
- 解耦:对于具体实现类只需要关注自己的业务,与创建者解耦
- 符合开闭原则,单一职责原则
使用场景
-
抽象产品(Product)
java.net.URLStreamHandler -
具体产品(ConcreteProduct)
org.apache.catalina.webresources.ClasspathURLStreamHandler
sun.net.www.protocol.http.Handler
… -
抽象工厂(AbstractFactory)
java.net.URLStreamHandlerFactory接口 -
具体工厂
org.apache.catalina.webresources.TomcatURLStreamHandlerFactory
org.springframework.boot.web.embedded.jetty.JasperInitializer.WarUrlStreamHandlerFactory
…
该场景主要用于创建不同类型的URLConnection,各个厂家都可以实现自己支持的URLConnection,如JDK支持http/https/jar资源,Spring Boot和Tomcat也是有自己的实现