收藏私塾在线
 

欢迎您来到私塾在线网!   

请登录! 

免费注册 


javasscc的笔记
状态: 离线
人气:499811
访问用户量:1134
笔记经验:1858
总积分:1958
级别:普通会员
搜索本笔记
ta的交流分类
ta的交流主题贴(196)
ta的所有交流贴(200)
ta的全部笔记
全部笔记(98)
未分类笔记(0)
研磨设计模式(94)
课程问题(0)
设计模式综合项目实战(4)
存档
2013-05(4)
2012-08(39)
2012-07(55)

2013-01-22 17:00:54
研磨设计模式之工厂方法模式-2 ——跟着cc学设计系列
浏览(6874)|评论(8)   交流分类:Java|笔记分类: 研磨设计模式

 

 

2  解决方案

2.1  工厂方法模式来解决

        用来解决上述问题的一个合理的解决方案就是工厂方法模式。那么什么是工厂方法模式呢?
(1)工厂方法模式定义
        定义一个用于创建对象的接口,让子类决定实例化哪一个类,Factory Method使一个类的实例化延迟到其子类。

 

(2)应用工厂方法模式来解决的思路
        仔细分析上面的问题,事实上在实现导出数据的业务功能对象里面,根本就不知道究竟要使用哪一种导出文件的格式,因此这个对象本就不应该和具体的导出文件的对象耦合在一起,它只需要面向导出的文件对象的接口就好了。
        但是这样一来,又有新的问题产生了:接口是不能直接使用的,需要使用具体的接口实现对象的实例。
        这不是自相矛盾吗?要求面向接口,不让和具体的实现耦合,但是又需要创建接口的具体实现对象的实例。怎么解决这个矛盾呢?
        工厂方法模式的解决思路很有意思,那就是不解决,采取无为而治的方式:不是需要接口对象吗,那就定义一个方法来创建;可是事实上它自己是不知道如何创建这个接口对象的,没有关系,那就定义成抽象方法就好了,自己实现不了,那就让子类来实现,这样这个对象本身就可以只是面向接口编程,而无需关心到底如何创建接口对象了。

2.2  模式结构和说明

        工厂方法模式的结构如图3所示:


                     图3  工厂方法模式结构示意图

Product
        定义工厂方法所创建的对象的接口,也就是实际需要使用的对象的接口。
ConcreteProduct:
        具体的Product接口的实现对象。
Creator:
        创建器,声明工厂方法,工厂方法通常会返回一个Product类型的实例对象,而且多是抽象方法。也可以在Creator里面提供工厂方法的默认实现,让工厂方法返回一个缺省的Product类型的实例对象。
ConcreteCreator:
        具体的创建器对象,覆盖实现Creator定义的工厂方法,返回具体的Product实例。

2.3  工厂方法模式示例代码

(1)先看看Product的定义,示例代码如下:

 

 

/**

* 工厂方法所创建的对象的接口

*/

public interface Product {

    //可以定义Product的属性和方法

}

(2)再看看具体的Product的实现对象,示例代码如下:

 

 

/**

* 具体的Product对象

*/

public class ConcreteProduct implements Product {

    //实现Product要求的方法

}

(3)接下来看看创建器的定义,示例代码如下:

 

 

/**

* 创建器,声明工厂方法

*/

public abstract class Creator {

    /**

    * 创建Product的工厂方法

    * @return Product对象

    */

    protected abstract Product factoryMethod();

    /**

    * 示意方法,实现某些功能的方法

    */

    public void someOperation() {

       //通常在这些方法实现中,需要调用工厂方法来获取Product对象

       Product product = factoryMethod();

    }

}

(4)再看看具体的创建器实现对象,示例代码如下:

 

 

/**

* 具体的创建器实现对象

*/

public class ConcreteCreator extends Creator {

    protected Product factoryMethod() {

       //重定义工厂方法,返回一个具体的Product对象

       return new ConcreteProduct();

    }

}

 

2.4  使用工厂方法模式来实现示例

        要使用工厂方法模式来实现示例,先来按照工厂方法模式的结构,对应出哪些是被创建的Product,哪些是Creator。分析要求实现的功能,导出的文件对象接口ExportFileApi就相当于是Product,而用来实现导出数据的业务功能对象就相当于Creator。把Product和Creator分开过后,就可以分别来实现它们了。
        使用工厂模式来实现示例的程序结构如图4所示:


                                 图4  使用工厂模式来实现示例的程序结构示意图
下面一起来看看代码实现。
(1)导出的文件对象接口ExportFileApi的实现没有变化,这里就不去赘述了
(2)接下来看看接口ExportFileApi的实现,为了示例简单,只实现导出文本文件格式和数据库备份文件两种。先看看导出文本文件格式的实现,示例代码如下:

 

 

/**

* 导出成文本文件格式的对象

*/

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)Creator这边的实现,首先看看ExportOperate的实现,示例代码如下:

 

 

/**

* 实现导出数据的业务功能对象

*/

public abstract class ExportOperate {

    /**

    * 导出文件

    * @param data 需要保存的数据

    * @return 是否成功导出文件

    */

    public boolean export(String data){

       //使用工厂方法

       ExportFileApi api = factoryMethod();

       return api.export(data);

    }

    /**

    * 工厂方法,创建导出的文件对象的接口对象

    * @return 导出的文件对象的接口对象

    */

    protected abstract ExportFileApi factoryMethod();

}

(4)加入了两个Creator实现,先看看创建导出成文本文件格式的对象,示例代码如下:

 

 

/**

* 具体的创建器实现对象,实现创建导出成文本文件格式的对象

*/

public class ExportTxtFileOperate extends ExportOperate{

    protected ExportFileApi factoryMethod() {

       //创建导出成文本文件格式的对象

       return new ExportTxtFile();

    }

}

再看看创建导出成数据库备份文件形式的对象,示例代码如下:

 

 

/**

* 具体的创建器实现对象,实现创建导出成数据库备份文件形式的对象

*/

public class ExportDBOperate extends ExportOperate{

    protected ExportFileApi factoryMethod() {

       //创建导出成数据库备份文件形式的对象

       return new ExportDB();

    }

}

(5)客户端直接创建需要使用的Creator对象,然后调用相应的功能方法,示例代码如下:

 

 

public class Client {

    public static void main(String[] args) {

       //创建需要使用的Creator对象

       ExportOperate operate = new ExportDBOperate();

       //调用输出数据的功能方法

       operate.export("测试数据");

    }

}

运行结果如下:

 

 

导出数据测试数据到数据库备份文件

 

        你还可以修改客户端new的对象,切换成其它的实现对象,试试看会发生什么。看来应用工厂方法模式是很简单的,对吧。

 

 

未完待续......

 


---------------------------------------------------------------------------

私塾在线学习网原创内容  跟着cc学设计系列 之 研磨设计模式

原创内容,转载请注明出处【http://sishuok.com/forum/blogPost/list/86.html

---------------------------------------------------------------------------



精品视频课程推荐

研磨设计模式——跟着cc学设计系列视频教程
本视频课程是北京Java私塾原创精品书籍《研磨设计模式》一书的配套学习视频,由《研磨设计模式》的第一作者CC录制 课程目标:全面、系统的掌握GoF设计模式的知识,达到可以在实际项目开发中运用的能力 技术要点:如何实现可配置、如何实现缓存以及缓存的管理、如何实现用缓存来控制多实例的创建、如何实现参数化工厂、 如何实现可扩展工厂、如何实现原型管理器、如何实现Java的静态代理和动态代理、如何实现多线程处理队列请求、 如何实现命令的参数化配置、可撤销的操作、宏命令、队列请求和日志请求、如何实现翻页迭代、如何检测环状结构、 如何实现通用的增删改查、如何模拟工作流来处理流程、如何实现简单又通用的XML读取、如何实现模拟AOP的功能......

freevoice(局域网对讲机)——Android4项目实战视频教程
实现通过Wifi来在局域网内相互传递信息和语音通话的功能;学习Service;Broadcast Receiver;SharedPreference;SQLite;语音录制、播放、传输等;网络开发:wifi处理、UDP编程、TCP编程;多种设计模式的应用 等等

软件系统功能设计实战训练视频教程
本课程是《软件系统功能设计实战训练》网络班的全套学习视频,通过6个具体的设计案例,综合应用几乎全部的GoF设计模式,以及多种设计理念和方法。 每个设计案例都各有侧重点,训练的难度会逐步加大,以切实帮助各位学员快速的掌握软件系统设计的方法,提升自己的软件系统设计能力。

Java高级视频教程-理论部分
Java程序设计基础、设计模式基础、框架的基本概念等知识。

《设计模式综合项目实战》——跟着cc学设计系列精品视频教程

浏览(6874)|评论(8)   交流分类:Java|笔记分类: 研磨设计模式

评论(8)
8楼 Do  2013-01-22 引用

ExportOperate operate = new ExportDBOperate(new ExportDB())

通过参数函数会更简单

7楼 seekbug  2013-01-14 引用

看看尴尬

6楼 fireliuwei  2012-11-15 引用

 

fireliuwei写

但是我觉得ExportOperate写export方法好像没什么用,因为可以直接 operate.factoryMethod().export("aaaaa"),

那为什么ExportOperate要写export方法呢?

 是不是为了好看?

5楼 fireliuwei  2012-11-15 引用

但是我觉得ExportOperate写export方法好像没什么用,因为可以直接 operate.factoryMethod().export("aaaaa"),

那为什么ExportOperate要写export方法呢?

4楼 fireliuwei  2012-11-15 引用

没错`我错了

3楼 fireliuwei  2012-11-15 引用

public class Client {

    public static void main(String[] args) {

       //创建需要使用的Creator对象

       ExportOperate operate = new ExportDBOperate();

       //调用输出数据的功能方法

       operate.export("测试数据");

    }

}

是不是有错啊

2楼 liangbangyu  2012-08-06 引用

继续学习,谢谢分享。

1楼 zhang  2012-07-04 引用

支持

请登录后评论 登录

关于我们 | 联系我们 | 用户协议 | 私塾在线服务协议 | 版权声明 | 隐私保护

版权所有 Copyright(C)2009-2012 私塾在线学习网