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

工厂方法模式

uml类图

这里写图片描述

定义

Define an interface for creating an object,but let subclasses decide which class to instance.
Factory Method lets a class defer instantiation to subclasses.

定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法是一个类的实例化延迟到其子类。

抽象产品类:负责定义产品的共性,实现对事物最抽象的定义
具体产品类:
抽象工厂类:对客户暴露的入口,负责定义工厂的功能
具体工厂类:

实现

  1. 抽象产品类(接口)

Machine.java

/**
 * @author heshiyuan
 * @description <p></p>
 * @path java-design-pattern/com.hsy.java.design.pattern.method
 * @date 2018/1/30 15:58
 * @github http://github.com/shiyuan2he
 * @email shiyuan4work@sina.com
 * Copyright (c) 2018 shiyuan4work@sina.com All rights reserved.
 * @price ¥5    微信:hewei1109
 */
public interface Machine {
    // 车发动起来
    void start() ;
    // 车加速度
    void speed() ;
    // 车制动
    void stop() ;
}
  1. 具体产品类

Car.java

/**
 * @author heshiyuan
 * @description <p></p>
 * @path java-design-pattern/com.hsy.java.design.pattern.method.product
 * @date 2018/1/30 16:03
 * @github http://github.com/shiyuan2he
 * @email shiyuan4work@sina.com
 * Copyright (c) 2018 shiyuan4work@sina.com All rights reserved.
 * @price ¥5    微信:hewei1109
 */
public class Car implements Machine{
    private final Logger _logger = LoggerFactory.getLogger(this.getClass()) ;
    @Override
    public void start() {
        _logger.info("汽车启动啦");
    }

    @Override
    public void speed() {
        _logger.info("汽车加速啦");
    }

    public void blow() {
        _logger.info("汽车按铃啦");
    }

    @Override
    public void stop() {
        _logger.info("汽车停车啦");
    }
}

Truck.java

/**
 * @author heshiyuan
 * @description <p></p>
 * @path java-design-pattern/com.hsy.java.design.pattern.method.product
 * @date 2018/1/30 16:04
 * @github http://github.com/shiyuan2he
 * @email shiyuan4work@sina.com
 * Copyright (c) 2018 shiyuan4work@sina.com All rights reserved.
 * @price ¥5    微信:hewei1109
 */
public class Truck implements Machine{
    private final Logger _logger = LoggerFactory.getLogger(this.getClass()) ;
    @Override
    public void start() {
        _logger.info("卡车启动啦");
    }

    @Override
    public void speed() {
        _logger.info("卡车加速啦");
    }

    public void blow() {
        _logger.info("卡车按铃啦");
    }

    @Override
    public void stop() {
        _logger.info("卡车停车啦");
    }
}

Bike.java

/**
 * @author heshiyuan
 * @description <p></p>
 * @path java-design-pattern/com.hsy.java.design.pattern.method.product
 * @date 2018/1/30 16:04
 * @github http://github.com/shiyuan2he
 * @email shiyuan4work@sina.com
 * Copyright (c) 2018 shiyuan4work@sina.com All rights reserved.
 * @price ¥5    微信:hewei1109
 */
public class Bike implements Machine{
    private final Logger _logger = LoggerFactory.getLogger(this.getClass()) ;
    @Override
    public void start() {
        _logger.info("自行车启动啦");
    }

    @Override
    public void speed() {
        _logger.info("自行车加速啦");
    }

    @Override
    public void stop() {
        _logger.info("自行车停车啦");
    }
}
  1. 抽象工厂类

Factory.java

/**
 * @author heshiyuan
 * @description <p></p>
 * @path java-design-pattern/com.hsy.java.design.pattern.method
 * @date 2018/1/30 15:57
 * @github http://github.com/shiyuan2he
 * @email shiyuan4work@sina.com
 * Copyright (c) 2018 shiyuan4work@sina.com All rights reserved.
 * @price ¥5    微信:hewei1109
 */
public abstract class Factory {

    public abstract <T extends Machine> T createMachine(Class<T> c);
}

MachineFactory.java

/**
 * @author heshiyuan
 * @description <p></p>
 * @path java-design-pattern/com.hsy.java.design.pattern.method
 * @date 2018/1/30 16:01
 * @github http://github.com/shiyuan2he
 * @email shiyuan4work@sina.com
 * Copyright (c) 2018 shiyuan4work@sina.com All rights reserved.
 * @price ¥5    微信:hewei1109
 */
public class MachineFactory extends Factory{
    @Override
    public <T extends Machine> T createMachine(Class<T> c) {
        Machine machine = null ;
        try {
            machine = (Machine) Class.forName(c.getName()).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return (T) machine;
    }
}
  1. 测试
/**
 * @author heshiyuan
 * @description <p></p>
 * @path java-design-pattern/com.hsy.java.design.pattern.method.client
 * @date 2018/1/30 16:13
 * @github http://github.com/shiyuan2he
 * @email shiyuan4work@sina.com
 * Copyright (c) 2018 shiyuan4work@sina.com All rights reserved.
 * @price ¥5    微信:hewei1109
 */
public class ClientTest {
    @Test
    public void createMachine(){
        // 打包给客户的集装箱
        List<Machine> list = new ArrayList<>() ;
        /**
         * 实例化一个造车工厂
         */
        Factory factory = new MachineFactory() ;
        /**
         * 1.客户下订单,开始造车(2辆汽车,2两卡车,2两自行车)
         */
        // 造汽车生产线
        for(int i=0;i<2;i++){
            list.add(factory.createMachine(Car.class));
        }
        // 造卡车生产线
        for(int i=0;i<2;i++){
            list.add(factory.createMachine(Truck.class));
        }
        // 造自行车生产线
        for(int i=0;i<2;i++){
            list.add(factory.createMachine(Bike.class));
        }

        //客户开始测验每辆车的性能
        list.forEach(ele -> {
            ele.start() ;
            ele.speed();
            ele.stop();
            if(ele instanceof Car){
                ((Car) ele).blow();
            }
            if(ele instanceof Truck){
                ((Truck) ele).blow();
            }
        });
    }
}

优点

  1. 良好的封装行,代码结构清晰
  2. 工厂方法模式的扩展性非常优秀。

    增加产品类的情况下,只要适当地修改具体的工厂类或扩展一个工厂类,就可以完成“拥抱变化”

  3. 屏蔽产品类

    产品类的实现如果变化,调用者不需要关心,它只需要关心产品的接口,只要接口保持不变,系统中的上层模块就不要发生变化。
    因为产品中的实例化工作是由工厂类负责的。

  4. 工厂方法模式是典型的解耦框架。

    高层模块需要知道产品的抽象类,其他的实现类都不用关心,符合迪米特法则-我不需要的就不要去交流

    也符合依赖倒置原则-只依赖产品类的抽象;

    也符合里氏替换原则-使用产品子类替换产品父类;

使用场景

  1. 工厂方法模式是new一个对象的替代品,所以在所有需要生成对象的地方都可以使用,但是需要慎重的考虑是否要增加一个工厂类进行管理,增加代码的复杂度;
  2. 需要灵活的、可扩展的框架时,可以考虑采用工厂方法模式。

    万物皆对象,那万物也就皆产品类,例如需要设计一个连接邮件服务器的框架,有三种网络协议可供选择:pop3、imap、http,我们就可以把这三种
    连接方法作为产品类,定义一个接口,然后定义对邮件的操作方法,用不同的方法实现三个具体的产品类,再定义一个工厂方法,按照不同的传入条件,
    选择不同的连接方式。如此设计,可以做到完美的扩展,如果某些邮件服务器提供了WebService接口,我们只要增加一个产品类就可以了。

  3. 工厂方法模式可以用在异构项目中。

    例如,通过webservice与一个非Java的项目交互,虽然WebService号称是可以做到异构系统的同构化,但是在实际的开发中,还是会碰到很多问题,
    如类型问题、wsdl文件的支持问题等。从WSDL中产生的对象都认为是一个产品,然后由一个具体的工厂类进行管理,减少与外围系统的耦合。

  4. 可以使用在测试驱动开发的框架下。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值