- 概述
属于创建型设计模式,需要生成的对象叫做产品 ,生成对象的地方叫做工厂 。
1.普通工厂模式
使用场景:
在任何需要生成复杂对象的地方,都可以使用工厂方法模式。
准备:
定义一个接口:
public interface Api {
public void say();
}
编写几个实现接口的方法:
public class Impl1 implements Api {
@Override
public void say() {
System.out.println("impl-1 实现");
}
}
public class Impl2 implements Api {
@Override
public void say() {
System.out.println("impl-2实现");
}
}
public class Impl3 implements Api {
@Override
public void say() {
System.out.println("impl-3实现");
}
}
1.1简单(静态)工厂:
public class SimpleFactory {
public static final int imp1 = 1;
public static final int imp2 = 2;
public static final int imp3 = 3;
//对象生成方法
public static Api createApi(int imp){
switch (imp) {
case imp1:
return new Impl1();
case imp2:
return new Impl2();
case imp3:
default:
return new Impl3();
}
}
//client方法
public static void main(String[] args) {
Api a = SimpleFactory.createApi(SimpleFactory.imp1);
a.say();
}
}
特点:
1 它是一个具体的类,非接口 抽象类。有一个重要的create()方法,利用if或者 switch创建产品并返回。
2 create()方法通常是静态的,所以也称之为静态工厂。
缺点:
1 扩展性差(我想增加一种面条,除了新增一个面条产品类,还需要修改工厂类方法)
2 不同的产品需要不同额外参数的时候 不支持。
1.2反射实现工厂模式:
public class ReflectFactory {
//对象生成方法
public static <T extends Api> T createApi(Class<T> t) {
T re = null;
try {
re = (T)Class.forName(t.getName()).newInstance();
}
catch (Exception e) {
e.printStackTrace();
}
return re;
}
//client方法
public static void main(String[] args) {
Api a = ReflectFactory.createApi(Impl1.class);
a.say();
}
}
特点
1 它也是一个具体的类,非接口 抽象类。但它的create()方法,是利用反射机制生成对象返回,好处是增加一种产品时,不需要修改create()的代码。
缺点
这种写法粗看牛逼,细想之下,不谈reflection的效率还有以下问题:
1 个人觉得不好,因为Class.forName(clz.getName()).newInstance()调用的是无参构造函数生成对象,它和new Object()是一样的性质,而工厂方法应该用于复杂对象的初始化 ,当需要调用有参的构造函数时便无能为力了,这样像为了工厂而工厂,与直接new创建没有太大差别。
2 不同的产品需要不同额外参数的时候 不支持。
1.3多方法工厂
public class MulFactory {
public static Api createImpl1(){
return new Impl1();
}
public static Api createImpl2(){
return new Impl2();
}
public static Api createImpl3(){
return new Impl3();
}
public static void main(String[] args) {
Api a = MulFactory.createImpl1();
a.say();
}
}
特点:
解决不同的产品需要不同额外参数的时候 不支持的问题。
而多方法的工厂模式为不同产品,提供不同的生产方法,使用时 需要哪种产品就调用该种产品的方法,使用方便、容错率高。
在线程池的工厂类Executors就是使用这个模式。
public class Executors {
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newWorkStealingPool(int parallelism) {
return new ForkJoinPool
(parallelism,
ForkJoinPool.defaultForkJoinWorkerThreadFactory,
null, true);
}
......
}
这个例子可以感受到工厂方法的魅力了吧:方便创建 同种类型的 复杂参数 对象。
2.工厂方法模式
工厂方法模式是简单工厂模式的衍生,解决了许多简单工厂模式的问题。首先完全实现‘开-闭 原则’,实现了可扩展。其次更复杂的层次结构,可以应用于产品结果复杂的场合。
工厂也由原先的方法编程接口如下:
public abstract class Factory {
public abstract Api createApi();
}
有接口就有接口的实现:
public class Implfactory1 extends Factory{
@Override
public Api createApi() {
return new Impl1();
}
public static void main(String[] args) {
Factory fac = new Implfactory1();
Api a =fac.createApi();
a.say();
}
}
因此没个对象都需要一个独立的工厂去进行声明,但是拥有相同的工厂接口。
优点:
创建对象的接口,让子类去决定具体实例化的对象,把简单的内部逻辑判断移到了客户端代码。工厂方法克服了简单工厂违背开放-封闭原则的缺点,又保持了封装对象创建过程的优点。
3抽象工厂模式
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
因为是一系列,因此我们需要更多的产品创建另一个产品的接口以及产品的一些实现:
public interface Apis {
public void says();
}
产品的实现:
public class Impls1 implements Apis {
@Override
public void says() {
System.out.println("Impls-1 实现");
}
}
接下来进行一些列产品的工厂类创建,首先进行工厂接口的编写:
public abstract class AbstractFactory {
public abstract Api createApi();
public abstract Apis createApis();
}
工厂类的实现(可以多实现,不同实现不同系列产品):
public class ExtendFactory extends AbstractFactory{
@Override
public Api createApi() {
return new Impl1();
}
@Override
public Apis createApis() {
return new Impls1();
}
public static void main(String[] args) {
AbstractFactory ab = new ExtendFactory();
ab.createApi().say();
ab.createApis().says();
}
}
4总结
一句话总结工厂模式:方便创建 同种产品类型的 复杂参数 对象
工厂模式重点就是适用于 构建同产品类型(同一个接口 基类)的不同对象时,这些对象new很复杂,需要很多的参数,而这些参数中大部分都是固定的,so,懒惰的程序员便用工厂模式封装之。
为了适应程序的扩展性,拥抱变化,便衍生出了 工厂方法模式、抽象工厂等模式。