注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

民主与科学

独立之人格,自由之思想

 
 
 

日志

 
 

工厂方法模式(Factory Method Pattern) 应用篇(下)  

2012-06-03 07:31:08|  分类: 设计模式 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
本文摘自:http://danielzzu.blog.163.com/blog/static/11851530420112311303240/
五、  使用工厂方法模式来实现
  所谓参数化工厂方法指的就是:通过给工厂方法传递参数,让工厂方法根据参数的不同来创建不同的产品对象,这种情况就被称为参数化工厂方法。当然工厂方法创建的不同的产品必须是同一个Product类型的。
  来改造前面的示例,现在有一个工厂方法来创建ExportFileApi这个产品的对象,但是ExportFileApi接口的具体实现很多,为了方便创建的选择,直接从客户端传入一个参数,这样在需要创建ExportFileApi对象的时候,就把这个参数传递给工厂方法,让工厂方法来实例化具体的ExportFileApi实现对象。
  还是看看代码示例会比较清楚。
(1)先来看Product的接口,就是ExportFileApi接口,跟前面的示例没有任何变化,为了方便大家查看,这里重复一下,示例代码如下: 

/**
 * 导出的文件对象的接口
 */
public interface ExportFileApi {
    /**
     * 导出内容成为文件
     * @param data 示意:需要保存的数据
     * @return 是否导出成功
     */
    public boolean export(String data);
}
(2)同样提供保存成文本文件和保存成数据库备份文件的实现,跟前面的示例没有任何变化,示例代码如下: 

public class ExportTxtFile implements ExportFileApi{
    public boolean export(String data) {
       //简单示意一下,这里需要操作文件
       System.out.println("导出数据"+data+"到文本文件");
       return true;
    }
}


public class ExportDB implements ExportFileApi{
    public boolean export(String data) {
       //简单示意一下,这里需要操作数据库和文件
       System.out.println("导出数据"+data+"到数据库备份文件");
       return true;
    }
}
(3)接下来该看看ExportOperate类了,这个类的变化大致如下:
ExportOperate类中的创建产品的工厂方法,通常需要提供默认的实现,不抽象了,也就是变成正常方法
ExportOperate类也不再定义成抽象类了,因为有了默认的实现,客户端可能需要直接使用这个对象
设置一个导出类型的参数,通过export方法从客户端传入
  看看代码吧,示例代码如下: 

/**
 * 实现导出数据的业务功能对象
 */
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;
    }
}
(4)此时的客户端,非常简单,直接使用ExportOperate类,示例代码如下: 

public class Client {
    public static void main(String[] args) {
        //创建需要使用的Creator对象
       ExportOperate operate = new ExportOperate();
       //调用输出数据的功能方法,传入选择到处类型的参数 
       operate.export(1,"测试数据");
    }
}
  测试看看,然后修改一下客户端的参数,体会一下通过参数来选择具体的导出实现的过程。这是一种很常见的参数化工厂方法的实现方式,但是也还是有把参数化工厂方法实现成为抽象的,这点要注意,并不是说参数化工厂方法就不能实现成为抽象类了。只是一般情况下,参数化工厂方法,在父类都会提供默认的实现。
(5)扩展新的实现
  使用参数化工厂方法,扩展起来会非常容易,已有的代码都不会改变,只要新加入一个子类来提供新的工厂方法实现,然后在客户端使用这个新的子类即可。
  这种实现方式还有一个有意思的功能,就是子类可以选择性覆盖,不想覆盖的功能还可以返回去让父类来实现,很有意思。
  先扩展一个导出成xml文件的实现,试试看,示例代码如下: 

/**
 * 导出成xml文件的对象
 */
public class ExportXml implements ExportFileApi{
    public boolean export(String data) {
       //简单示意一下
       System.out.println("导出数据"+data+"到XML文件");
        return true;
    }
}
然后扩展ExportOperate类,来加入新的实现,示例代码如下: 

/**
 * 扩展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;
    }
}

看看此时的客户端,也非常简单,只是在变换传入的参数,示例代码如下: 

public class Client {
    public static void main(String[] args) {
       //创建需要使用的Creator对象
       ExportOperate operate = new ExportOperate2();
       //下面变换传入的参数来测试参数化工厂方法
       operate.export(1,"Test1");
       operate.export(2,"Test2");
       operate.export(3,"Test3");
    }
} 
对应的测试结果如下: 
导出数据Test1到文本文件
导出数据Test2到数据库备份文件
导出数据Test3到XML文件
通过上面的示例,好好体会一下参数化工厂方法的实现和带来的好处。
  评论这张
 
阅读(574)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017