工厂方法模式介绍
在OO编程中,创建对象实例的方法一般都是通过new操作符,但是在某些情况下,new操作符直接生成对象会带来问题,比如对象的创造需要一系列的步骤;需要计算后才能得到对象的初始值;选择生成哪个子类对象。对于上述的情况,一个对象的创建就好像是一个过程,为了屏蔽复杂的创建过程,提出了工厂模式的设计思想。
工厂方法的定义
定义一个用于创建对象的接口,让子类决定实例化哪个对象。
工厂方法的使用场景
在任何需要生成复杂对象的地方,都可以使用工厂方法模式。复杂对象适合使用工厂模式,用new可以完成创建的对象无需使用工厂模式
工厂方法的UML类图
工厂方法中一般有四大模块:
- 抽象工厂:是工厂方法模式的核心
- 具体工厂:实现了具体的业务逻辑
- 抽象产品:工厂方法模式所创建的产品的父类
- 具体产品:实现抽象产品的某个具体产品的对象。
工厂方法多有个表现形式:
- 简单工厂方法(又称静态工厂模式)
- 工厂方法
- 抽象工厂方法
简单工厂方法(静态工厂模式)
简单工厂方法,明确了工厂类只有一个,因此不需要为工厂提供抽象类,因此将工厂方法改为静态方法即可。
简单工厂方法如下:
public class PizzaStore {
public Pizza orderPizza(String type) {
Pizza pizza;
pizza = createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
//简单工厂方法(静态工厂方法)
public static Pizza createPizza(String type) {
if ("CHINA".equals(type)) {
return new ChinaStyleOnePizza();
} else if ("NY".equals(type)) {
return new NYStyleOnePizza();
}
return null;
}
}
工厂方法
工厂方法的UML类图如下:
在图中,Pizza是抽象产品,ChinaStylePizza、NYStylePizza是具体产品,PizzaStore是抽象工厂,ChinaStylePizzaStore、NYStylePizzaStore是具体的工厂。
ChinaStylePizzaStore的代码如下:
public class ChinaStyleStore extends PizzaStore {
@Override
protected <T extends Pizza> T createPizza(Class<T> clz) {
Pizza pizza = null;
try {
pizza = (Pizza) Class.forName(clz.getName()).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return (T) pizza;
}
}
在该具体工厂中使用反射的方式,更加简洁的生产具体产品对象。
抽象工厂方法
抽象工厂方法主要是具有多个产品,多个工厂,属于工厂方法的变种。暂不做讨论
工厂方法的简单实例
Pizza抽象产品:
public abstract class Pizza {
protected String name; //名称
protected String dough; //面团类型
protected String sauce; //酱料类型
protected ArrayList toppings = new ArrayList(); //佐料
void prepare(){
System.out.println("Preparing " + name);
System.out.println("Tossing dough..."); //搅拌面团
System.out.println("Adding sauce..."); //添加酱料
System.out.println("Adding toppings: "); //添加佐料
for (Object topping : toppings) {
System.out.println(" " + topping);
}
}
void bake(){
System.out.println("Bake for 25 minutes at 350");
}
void cut(){
System.out.println("Cutting the pizza into diagonal slices");
}
void box(){
System.out.println("Please pizza in official PizzaStore box");
}
public String getName(){
return name;
}
}
抽象工厂PizzaStore类
public abstract class PizzaStore {
public Pizza orderPizza(Class clz){
Pizza pizza;
pizza = createPizza(clz);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
protected abstract <T extends Pizza> T createPizza(Class<T> clz);
}
具体产品
public class NYStyleOnePizza extends Pizza {
public NYStyleOnePizza() {
name = "NY Style and One Pizza";
dough = "NY Style One dough";
sauce = "NY Style One sauce";
toppings.add("NY Style One topping");
}
}
public class ChinaStyleOnePizza extends Pizza {
public ChinaStyleOnePizza() {
name = "China Style One Pizza";
sauce = "China Style One sauce";
dough = "China Style One dough";
toppings.add("China Style One toppings");
}
}
具体工厂
public class ChinaStyleStore extends PizzaStore {
@Override
protected <T extends Pizza> T createPizza(Class<T> clz) {
Pizza pizza = null;
try {
pizza = (Pizza) Class.forName(clz.getName()).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return (T) pizza;
}
}
Retrofit中的工厂方法
retrofit使用了工厂方法,其中一个例子就是CallAdapter。
//通过converter转换器将call<T>对象转换成java对象
public interface CallAdapter<R, T> {
//type代表实参
Type responseType();
//返回一个代表call的实例
T adapt(Call<R> call);
abstract class Factory {
//返回call adapter的接口方法的调用适配器,如果工厂未处理,则返回null
public abstract @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,
Retrofit retrofit);
//从{@code type}中提取{@code index}处的泛型参数的上限。例如,{@code Map <String的索引1,? extends Runnable>}返回{@code Runnable}。
protected static Type getParameterUpperBound(int index, ParameterizedType type) {
return Utils.getParameterUpperBound(index, type);
}
//返回type
protected static Class<?> getRawType(Type type) {
return Utils.getRawType(type);
}
}
}
与上述Pizza的例子不同的是,这里的工厂方法的抽象产品使用了interface接口类,而不是抽象类。在CallAdapter这个抽象类中,定义了内部抽象类Factory,而Factory中定义了get()这个抽象工厂方法,因此不同的工厂需要对这个get方法进行适配。
具体工厂类就有RxJava2CallAdapterFactory、RxJavaCallAdapterFactory、GuavaCallAdapterFactory等,这里以RxJava2为例
public final class RxJava2CallAdapterFactory extends CallAdapter.Factory {
/**
* Returns an instance which creates synchronous observables that do not operate on any scheduler
* by default.
*/
public static RxJava2CallAdapterFactory create() {
return new RxJava2CallAdapterFactory(null, false);
}
/**
* Returns an instance which creates asynchronous observables. Applying
* {@link Observable#subscribeOn} has no effect on stream types created by this factory.
*/
public static RxJava2CallAdapterFactory createAsync() {
return new RxJava2CallAdapterFactory(null, true);
}
/**
* Returns an instance which creates synchronous observables that
* {@linkplain Observable#subscribeOn(Scheduler) subscribe on} {@code scheduler} by default.
*/
@SuppressWarnings("ConstantConditions") // Guarding public API nullability.
public static RxJava2CallAdapterFactory createWithScheduler(Scheduler scheduler) {
if (scheduler == null) throw new NullPointerException("scheduler == null");
return new RxJava2CallAdapterFactory(scheduler, false);
}
private final @Nullable Scheduler scheduler;
private final boolean isAsync;
private RxJava2CallAdapterFactory(@Nullable Scheduler scheduler, boolean isAsync) {
this.scheduler = scheduler;
this.isAsync = isAsync;
}
@Override public @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {
Class<?> rawType = getRawType(returnType);
if (rawType == Completable.class) {
// Completable is not parameterized (which is what the rest of this method deals with) so it
// can only be created with a single configuration.
return new RxJava2CallAdapter(Void.class, scheduler, isAsync, false, true, false, false,
false, true);
}
boolean isFlowable = rawType == Flowable.class;
boolean isSingle = rawType == Single.class;
boolean isMaybe = rawType == Maybe.class;
if (rawType != Observable.class && !isFlowable && !isSingle && !isMaybe) {
return null;
}
boolean isResult = false;
boolean isBody = false;
Type responseType;
if (!(returnType instanceof ParameterizedType)) {
String name = isFlowable ? "Flowable"
: isSingle ? "Single"
: isMaybe ? "Maybe" : "Observable";
throw new IllegalStateException(name + " return type must be parameterized"
+ " as " + name + "<Foo> or " + name + "<? extends Foo>");
}
Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType);
Class<?> rawObservableType = getRawType(observableType);
if (rawObservableType == Response.class) {
if (!(observableType instanceof ParameterizedType)) {
throw new IllegalStateException("Response must be parameterized"
+ " as Response<Foo> or Response<? extends Foo>");
}
responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
} else if (rawObservableType == Result.class) {
if (!(observableType instanceof ParameterizedType)) {
throw new IllegalStateException("Result must be parameterized"
+ " as Result<Foo> or Result<? extends Foo>");
}
responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
isResult = true;
} else {
responseType = observableType;
isBody = true;
}
return new RxJava2CallAdapter(responseType, scheduler, isAsync, isResult, isBody, isFlowable,
isSingle, isMaybe, false);
}
}
在RxJava2CallAdapterFactory方法中,get方法配置了RxJava2所需要属性,然后返回一个RxJava2CallAdapter对象。
产品类有RxJava2CallAdapter、 RxJavaCallAdapter等
final class RxJava2CallAdapter<R> implements CallAdapter<R, Object> {
private final Type responseType;
private final @Nullable Scheduler scheduler;
private final boolean isAsync;
private final boolean isResult;
private final boolean isBody;
private final boolean isFlowable;
private final boolean isSingle;
private final boolean isMaybe;
private final boolean isCompletable;
RxJava2CallAdapter(Type responseType, @Nullable Scheduler scheduler, boolean isAsync,
boolean isResult, boolean isBody, boolean isFlowable, boolean isSingle, boolean isMaybe,
boolean isCompletable) {
this.responseType = responseType;
this.scheduler = scheduler;
this.isAsync = isAsync;
this.isResult = isResult;
this.isBody = isBody;
this.isFlowable = isFlowable;
this.isSingle = isSingle;
this.isMaybe = isMaybe;
this.isCompletable = isCompletable;
}
@Override public Type responseType() {
return responseType;
}
@Override public Object adapt(Call<R> call) {
Observable<Response<R>> responseObservable = isAsync
? new CallEnqueueObservable<>(call)
: new CallExecuteObservable<>(call);
Observable<?> observable;
if (isResult) {
observable = new ResultObservable<>(responseObservable);
} else if (isBody) {
observable = new BodyObservable<>(responseObservable);
} else {
observable = responseObservable;
}
if (scheduler != null) {
observable = observable.subscribeOn(scheduler);
}
if (isFlowable) {
return observable.toFlowable(BackpressureStrategy.LATEST);
}
if (isSingle) {
return observable.singleOrError();
}
if (isMaybe) {
return observable.singleElement();
}
if (isCompletable) {
return observable.ignoreElements();
}
return RxJavaPlugins.onAssembly(observable);
}
}