标签:
问题描述:
通常在导出数据上会有一些约定的格式,比如导出成文本格式,数据库备份形式,Excel格式,Xml格式。
对于实现数据导出的业务功能对象,它需要创建ExportFileApi的具体实现对象,但是它知道ExportFileApi接口,而不知道其具体的实现,那该怎么办?
工厂方法模式的定义:
定义一个用于创建对象的接口,让子类决定去实例化哪一个类,Factory Method使一个类的实现化延迟到其子类。
Product:定义工厂方法所创建的对象的接口,也就是实现需要使用的对象的接口
ConcreteProduct:Product的实现对象
Creator:声明工厂方法,工厂方法通常会返回一个Product类的实例对象,而且多是抽象方法
ConcreteCreator:覆盖实现Creator定义的工厂方法,返回具体的Product实例
具体代码:
/**
* 导出的文件对象的接口
*/
public interface ExportFileApi {
/**
* 导出内容成为文件
* @param data 示意:需要保存的数据
* @return 是否导出成功
*/
public boolean export(String data);
}
/**
* 导出成数据库备份文件形式的对象
*/
public class ExportDB implements ExportFileApi{
public boolean export(String data) {
//简单示意一下,这里需要操作数据库和文件
System.out.println("导出数据"+data+"到数据库备份文件");
return true;
}
}
/**
* 导出成文本文件格式的对象
*/
public class ExportTxtFile implements ExportFileApi{
public boolean export(String data) {
//简单示意一下,这里需要操作文件
System.out.println("导出数据"+data+"到文本文件");
return true;
}
}
/**
* 实现导出数据的业务功能对象
*/
public abstract class ExportOperate {
/**
* 导出文件
* @param data 需要保存的数据
* @return 是否成功导出文件
*/
public boolean export(String data){
//使用工厂方法
ExportFileApi api = factoryMethod();
return api.export(data);
}
/**
* 工厂方法,创建导出的文件对象的接口对象
* @return 导出的文件对象的接口对象
*/
protected abstract ExportFileApi factoryMethod();
}
/**
* 具体的创建器实现对象,实现创建导出成数据库备份文件形式的对象
*/
public class ExportDBOperate extends ExportOperate{
protected ExportFileApi factoryMethod() {
//创建导出成数据库备份文件形式的对象
return new ExportDB();
}
}
/**
* 具体的创建器实现对象,实现创建导出成文本文件格式的对象
*/
public class ExportTxtFileOperate extends ExportOperate{
protected ExportFileApi factoryMethod() {
//创建导出成文本文件格式的对象
return new ExportTxtFile();
}
}
public class Client {
public static void main(String[] args) {
//创建需要使用的Creator对象
ExportOperate operate = new ExportDBOperate();
//调用输出数据的功能方法
operate.export("测试数据");
}
}
工厂方法模式的功能主要是父类在不知道具体实现的情况下,完成自身的功能调用,而具体的实现让子类去做。
工厂方法的本质:延迟到子类去选择实现,有更好的维护性和可扩展性
一般不会把工厂方法暴露给客户端
IOC和DI
IOC Inversion Of Control 控制反转
DI Dependency Injection 依赖注入
依赖注入和控制反转是同一件事情的不同描述
依赖注入:从应用程序的角度描述,应用程序依赖容器创建并注入它所需要的外部资源;
控制反转:从容器的角度描述,容器控制应用程序,由容器反向地向程序注入其所需要的外部资源。
1. 参与者有谁:一个是某个Java对象,另一个是IOC/DI的容器,还有一个是某个对象的外部资源
2. 谁依赖于谁:某个Java对象依赖于IOC/DI的容器
3. 为什么需要依赖:对象需要IOC/DI容器来提供对象需要的外部资源
4. 谁注入谁:IOC/DI容器注入某个外部资源
5. 到底注入什么:注入某个对象所需的外部资源
6. 谁控制谁:IOC/DI的容器控制对象
7. 控制什么:控制对象实例的创建
参数化工厂方法值的是:通过给工厂方法传递参数,让工厂方法根据参数的不同创建不同的产品对象。
/**
* 实现导出数据的业务功能对象
*/
public class ExportOperate {
/**
* 导出文件
* @param type 用户选择的导出类型
* @param data 需要保存的数据
* @return 是否成功导出文件
*/
public boolean export(int type,String data){
//使用工厂方法
ExportFileApi api = factoryMethod(type);
return api.export(data);
}
/**
* 工厂方法,创建导出的文件对象的接口对象
* @param type 用户选择的导出类型
* @return 导出的文件对象的接口对象
*/
protected ExportFileApi factoryMethod(int type){
ExportFileApi api = null;
//根据类型来选择究竟要创建哪一种导出文件对象
if(type==1){
api = new ExportTxtFile();
}else if(type==2){
api = new ExportDB();
}
return api;
}
}
public class Client {
public static void main(String[] args) {
// //创建需要使用的Creator对象
// ExportOperate operate = new ExportOperate();
// //调用输出数据的功能方法,传入选择到处类型的参数
// operate.export(1,"测试数据");
//创建需要使用的Creator对象
ExportOperate operate = new ExportOperate2();
//下面变换传入的参数来测试参数化工厂方法
operate.export(1,"Test1");
operate.export(2,"Test2");
operate.export(3,"Test3");
}
}
//扩展非常容易
/**
* 扩展ExportOperate对象,加入可以导出XML文件
*/
public class ExportOperate2 extends ExportOperate{
/**
* 覆盖父类的工厂方法,创建导出的文件对象的接口对象
* @param type 用户选择的导出类型
* @return 导出的文件对象的接口对象
*/
protected ExportFileApi factoryMethod(int type){
ExportFileApi api = null;
//可以全部覆盖,也可以选择自己感兴趣的覆盖,
//这里只想添加自己新的实现,其他的不管
if(type==3){
api = new ExportXml();
}else{
//其他的还是让父类来实现
api = super.factoryMethod(type);
}
return api;
}
}
标签:
原文地址:http://blog.csdn.net/jiangxishidayuan/article/details/51865574