工厂 模式

工厂模式

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

工厂模式,也叫作静态工厂模式,顾名思义,就是用来生产对象的,在java中,万物皆对象,这些对象都需要创建,如果创建的时候直接new该对象,就会对该对象耦合严重,假如我们要更换对象,所有new对象的地方都需要修改一遍,这显然违背了软件设计的开闭原则,如果我们使用工厂来生产对象,我们就只和工厂打交道就可以了,彻底和对象解耦,如果要更换对象,直接在工厂里更换该对象即可,达到了与对象解耦的目的;所以说,工厂模式最大的优点就是:解耦

核心本质:

  • 实例化对象,用工厂的方法代替new对象
  • 选择具体的实现类,创建对象统一管理和控制,实现调用者和实现类的解耦,创建者和调用者的分离

场景:

  1. JDK中Calendar的getInstance方法;
  2. JDBC中Connection对象的获取;
  3. Hibernate中SessionFactory创建Session;
  4. spring中IOC容器创建管理bean对象;
  5. XML解析时的DocumentBuilderFactory创建解析器对象;
  6. 反射中Class对象的newInstance()

详细分类:

  1. 简单工厂模式:

    用来生产同一等级结构中的任意产品。

    (对于增加新的产品,需要修改已有代码);虽然某种程度不符合设计原则,但实际使用最多。

  2. 工厂方法模式:

    用来生产同一等级结构中的固定产品。

    (支持增加任意产品);不修改已有类的前提下,通过增加新的工厂类实现扩展。

  3. 抽象工厂模式:

    用来生产不同产品族的全部产品。

    (对于增加新的产品,无能为力;支持增加产品族);不可以增加产品,可以增加产品族!

工厂方法模式和简单工厂模式区别

简单工厂模式只有一个(对于一个项目或者一个独立模块而言)工厂类,而工厂方法模式有一组实现了相同接口的工厂类。

  1. 结构复杂度:

    从这个角度比较,显然简单工厂模式要占优。简单工厂模式只需一个工厂类,而工厂方法模式的工厂类随着产品类个数增加而增加,这无疑会使类的个数越来越多,从而增加了结构的复杂程度。

  2. 代码复杂度:

    代码复杂度和结构复杂度是一对矛盾,既然简单工厂模式在结构方面相对简洁,那么它在代码方面肯定是比工厂方法模式复杂的了。简单工厂模式的工厂类随着产品类的增加需要增加很多方法(或代码),而工厂方法模式每个具体工厂类只完成单一任务,代码简洁。

  3. 客户端编程难度:

    工厂方法模式虽然在工厂类结构中引入了接口从而满足了OCP,但是在客户端编码中需要对工厂类进行实例化。而简单工厂模式的工厂类是个静态类,在客户端无需实例化,这无疑是个吸引人的优点。

面向对象设计的基本原则

  1. OCP(开闭原则,Open-Closed Principle):

    一个软件的实体应当对扩展开放,对修改关闭。

  2. DIP(依赖倒转原则,Dependence Inversion Principle):

    要针对接口编程,不要针对实现编程。

  3. LoD(迪米特法则,Law of Demeter):

    只与你直接的朋友通信,而避免和陌生人通信。

案例

小明骑自行车去学校,开汽车去旅游,可用简单工厂模式实现

第一步,建一个交通工具接口,汽车和自行车都实现这个接口

/**
 * 交通工具
 */
interface IVehicle {
    void run();
}

//汽车
class Car implements IVehicle{
    @Override
    public void run() {
        System.out.println("开汽车去。。。");
    }
}

//自行车
class Bicycle implements IVehicle{
    @Override
    public void run() {
        System.out.println("骑自行车去。。。");
    }
}

第二步,创建车库,也就是工厂,来根据传入的参数确定返回的交通工具

//车库
public class GarageFactory {
    public static IVehicle getVehicle(String type) {
        if ("car".equals(type)) {
            return new Car();
        } else if ("bicycle".equals(type)) {
            return new Bicycle();
        }
        throw new IllegalArgumentException("请输入车类型");
    }
}

第三步,调用工厂方法

public class TestSimpleFactory {
    public static void main(String[] args) {
        XiaoMing xiaoMing = new XiaoMing();
        // 小明骑自行车去学校
        IVehicle motorcycle = GarageFactory.getVehicle("bicycle");
        xiaoMing.goToSchool(motorcycle);
        // 小明开汽车去旅游
        IVehicle car = GarageFactory.getVehicle("car");
        xiaoMing.travel(car);

    }
}

class XiaoMing{
    public void goToSchool(IVehicle vehicle){
        System.out.println("小明去学校:");
        vehicle.run();
    }
    public void travel(IVehicle vehicle){
        System.out.println("小明去旅游:");
        vehicle.run();
    }
}

缺点:

简单工厂模式拓展性不好,优秀的java代码是符合“开放-封闭”原则的,也就是说对扩展开发,对修改关闭

如果想骑电动车去上班,在这里就要增加if-else判断。对于这个问题,我们的工厂方法模式就可以解决这个问题。

工厂方法模式

根据上面的例子,如果有车库,则可以按车类型来放置。只需要在上面例子的基础上,再加2步。

第一步:建一个车库接口,汽车和自行车都实现这个接口

将车库提取抽象为一个接口,也就是有自行车车库和汽车车库来实现这个接口

public interface VehicleGarage {
    IVehicle getVehicle();
}

//汽车车库
class CarGarage implements VehicleGarage{
    @Override
    public IVehicle getVehicle() {
        return new Car();
    }
}

//自行车车库
class BicycleGarage implements VehicleGarage{
    @Override
    public IVehicle getVehicle() {
        return new Bicycle();
    }
}

第二部,调用

根据不同需求,使用不同的车库工厂类来获取交通工具

public class TestFactoryMethod {
    public static void main(String[] args) {

        XiaoMing xiaoMing = new XiaoMing();
        //小明骑自行车去学校
        BicycleGarage bicycleGarage = new BicycleGarage();
        IVehicle bicycle = bicycleGarage.getVehicle();
        xiaoMing.goToSchool(bicycle);

        //小明开汽车去旅游
        CarGarage carGarage = new CarGarage();
        IVehicle car = carGarage.getVehicle();
        xiaoMing.travel(car);
    }
}

工厂方法模式比简单工厂模式更具有扩展性

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值