Java设计模式之工厂方法模式

2.工厂方法(FactoryMethod)

1)场景问题

      用户向工厂下手机订单,工厂能生产Phone5S和Phone6E两种型号的手机。

工厂要生产满足用户需求的手机,有足够的资源材料,但是流水线上的操作人员并不知道用户究竟要使用哪一种版本型号。

 

2)问题描述

实现一个功能对象,需要创建功能接口的具体实例对象,但是只知道有这个接口,不知道其具体的实现

 

3)解决方案

模式定义:

定义一个用于创建对象的接口,让子类决定实例化哪一个类,Factory Method使一个类的实例化延迟到其子类。

模式结构:

Product:定义工厂方法所创建的对象的接口,也就是实际需要使用的对象的接口。

ConcreteProduct:具体的Product接口的实现对象。

Creator:创建器,声明工厂方法,工厂方法通常会返回一个Product类型的实例对象,而且多是抽象方法。也可以在Creator里面提供工厂方法的默认实现,让工厂方法返回一个缺省的Product类型的实例对象。

ConcreteCreator:具体的创建器对象,覆盖实现Creator定义的工厂方法,返回具体的Product实例。

 

4)示例代码

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

/**

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

 */

publicinterfaceProduct{

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

}

(2)Product实现对象的示例代码如下:

/**

 * 具体的Product对象

 */

publicclassConcreteProductimplementsProduct{

//实现Product要求的方法

}

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

/**

 * 创建器,声明工厂方法

 */

publicabstractclassCreator{

    /**

     * 创建Product的工厂方法

     * @return Product对象

     */

    protectedabstractProductfactoryMethod();

    /**

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

     */

    publicvoidsomeOperation(){

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

        Product Product =factoryMethod();

    }

}

(4)创建器实现对象的示例代码如下:

/**

 * 具体的创建器实现对象

 */

publicclassConcreteCreatorextendsCreator{

    protectedProductfactoryMethod(){

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

        returnnewConcreteProduct();

    }

}

 

5)优缺评价

优点

·可以在不知具体实现的情况下编程

选择具体实现的任务延迟到子类完成

·更容易扩展对象的新版本

只要新加入一个子类来提供新的工厂方法实现,然后在客户端使用这个新的子类即可。

·连接平行的类层次

缺点

·具体产品对象和工厂方法的耦合性

工厂方法模式中,工厂方法是需要创建产品对象的,也就是需要选择具体的产品对象并创建实例,因此具体产品对象和工厂方法是耦合的

 

6)适用场合

使用工厂方法实现示例:

先来按照工厂方法模式的结构,对应出哪些是被创建的Product,哪些是Creator。分析要求实现的功能,要生产的手机型号接口就相当于是Product,而用来实现生产手机的业务功能对象就相当于Creator。把Product和Creator分开后,就可以分别来实现它们了。

/**

 * 生产的手机对象的接口 */

publicinterfacePhoneApi{

    publicbooleanproduct(String type);

}

 

/**

 * 生产IPhone5s的手机

 */

publicclassPhone5SimplementsPhoneApi{

    publicbooleanproduct(String type){

        //选择生产IPhone5s的手机

        System.out.println("生产了型号为"+ type +"Phone5S手机");

        returntrue;

    }

}

 

/**

 * 生产IPhone6e的手机

 */

publicclassPhone6EimplementsPhoneApi{

    publicbooleanproduct(String type){

        //选择生产IPhone6e的手机

        System.out.println("生产了型号为"+ type +"Phone6E手机");

        returntrue;

    }

}

 

实现生产操作的代码如下:

**

* 实现生产手机的业务功能对象

*/

publicabstractclassProductOperate{

    /**

     * 生产手机

     * @param type 需要生产的型号

     * @return是否成功生产

     */

    publicbooleanproduct(String type){

        //使用工厂方法

        PhoneApi api =factoryMethod();

        return api.product(type);

    }

    /**

     * 工厂方法,创建生产的手机对象的接口对象

     * @return生产的手机对象的接口对象

     */

    protectedabstractPhoneApifactoryMethod();

}

加入两个具体Creator实现:

实现生产Phone5S型号手机的代码如下:

/**

 * 具体的手机生产对象,实现生产Phone5S的对象

 */

publicclassProductPhone5SOperateextendsProductOperate{

    protectedPhoneApifactoryMethod(){

        //创建生产Phone5S的手机类型的对象

        returnnewPhone5S();

    }

}

实现生产Phone6E型号手机的代码如下:

/**

 * 具体的手机生产对象,实现生产Phone6E的对象

 */

publicclassProductPhone6EOperateextendsProductOperate{

    protectedPhoneApifactoryMethod(){

        //创建生产Phone5S的手机类型的对象

        returnnewPhone6E();

    }

}

 

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

publicclassClient{

    publicstaticvoidmain(String[] args){

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

        ProductOperate operate =newProductPhone6EOperate();

        //调用显示生产内容的功能方法

        operate.product("Phone6E001");

    }

}

运行结果如下:

 

还可以修改客户端new的对象,切换成其他对象。

 

7)相关延伸

依赖注入/控制反转;

工厂方法模式和IOC/DI的思想很类似

A1里面要使用C1对象,不是由A1主动去获取C1对象,

而是创建一个工厂方法,类似于一个注入的途径;

然后由子类,假设叫A2,由A2来获取C1对象,

在调用的时候替换掉A1的相应方法,

相当于反向注入回到A1里面。

示例代码如下:

publicabstractclassA1{

    /**

     * 工厂方法,创建C1,类似于从子类注入进来的途径

     *

     * @return C1的对象实例

     */

    protectedabstractC1createC1();

 

    publicvoidt1(){

        // 这里需要使用C1类,可是不知道究竟是用哪一个

        // 也就不主动去创建C1了,怎么办?

        // 反正会在子类里面实现们这里不用管怎么获取C1,直接使用就好了

        createC1().tc();

    }

}

子类代码如下

publicclass A2 extends A1 {

    protected C1 createC1(){

        //真正的选择具体实现,并创建对象

        return new C2();

    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值