考虑一个场景:
某公司需要使用文件导出系统将某些数据打包到服务器上,但是现在还不知道打包的方式和文件的类型。
也即只知道有导出这样一个接口,但不知道具体实现。
客户端只需要调用抽象的接口对象中的方法,而不用关心具体实现。
定义:
定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法模式使一个类的实例化延迟到其子类。
角色:
Product:
定义工厂方法所创建的对象的接口,也就是实际需要使用的对象的接口
package com.kris.study; public interface Product { //可以定义属性和方法 public void doSomething(); }
ConcreteProduct:
具体Product对象
package com.kris.study; public class ConcreteProduct implements Product{ @Override public void doSomething() { System.out.println("生产商品"); } }
Creator:
创建器,声明工厂方法,工厂方法通常会返回一个Product类型的实例对象,而且多是抽象方法.也可以在Creator里面提供
工厂方法的默认实现,让工厂方法返回一个缺省的Product类型的实例对象
package com.kris.study; public abstract class Creator { protected abstract Product factoryMethod(); public void someOperation(){ Product product = factoryMethod(); product.doSomething(); } }
ConcreteCreator:
具体创建的对象,覆盖实现Creator定义的工厂方法,返回具体的Product实例
package com.kris.study; public class ConcreteCreator extends Creator { @Override protected Product factoryMethod() { return new ConcreteProduct(); } }
客户端调用:
可以使用new新建具体的Creator子类也可以传入参数由父类决定使用哪一个子类就像简单工厂.
package com.kris.study; public class Client { public static void main(String[] args) { Creator creator = new ConcreteCreator(); creator.someOperation(); } }
原理分析:
工厂方法模式的主要功能是让父类不知道具体实现的情况下,完成自身的功能调用; 而具体的实现延迟到子类。
也就是在工厂方法的父类中会有使用这些产品对象来实现一定功能的方法,而这些产品对象是由子类来提供.
工厂方法模式与IoC/DI
IoC:控制反转
DI:依赖注入
1)参与者
一般有三个参与者,一个是某个对象,另一个是IoC/DI容器,还有一个是某个对象的外部资源
2)谁依赖于谁
某个对象依赖于IoC/DI容器
3)为什么需要依赖
对象需要容器提供某个对象需要的外部资源
4)谁注入谁
容器注入某个对象
5)注入什么
注入某个对象需要的外部资源
6)谁控制谁
容器控制某个对象
7)控制什么
控制对象实例的创建
依赖注入是以应用程序的角度去看,应用程序依赖于容器创建并注入他所需要的外部资源
控制反转是以容器的角度去看,容器控制应用程序,由容器反向的向应用程序注入需要的外部资源
工厂方法模式和IoC/DI在思想上非常相似,都是主动变被动。
参数化工厂方法:通过给工厂方法传递参数,让工厂方法根据参数的不同来创建不同的产品对象。这时候工厂父类会有
一个默认的实现。
工厂方法模式优点:
在不知具体实现下实现功能方法,更容易扩展,连接平行的类层次结构.
缺点:
增加了具体产品对象与工厂方法的耦合性
本质:延迟到子类来选择实现
与简单工厂的不同:
简单工厂是在工厂类里面直接进行选择实现。
工厂方法会把这个具体实现的工作延迟到子类进行.工厂类里面的使用工厂方法的地方是依赖于抽象而不是具体的实现。
何时使用工厂方法
①一个类需要创建某个接口的对象,但是又不知道具体的实现.
②一个类希望由它的子类来创建某个方法需要的对象.