设计模式之工厂模式

概念

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

简单说就是专门负责将大量有共同接口的类实例化,而且不必事先知道每次是要实例化哪一个类的模式。

它定义一个用于创建对象的接口,由子类决定实例化哪一个类。工厂模式相当于创建实例对象的new,经常要根据类Class生成实例对象。

意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。

主要解决:主要解决接口选择的问题。

何时使用:我们明确地计划不同条件下创建不同实例时。

如何解决:让其子类实现工厂接口,返回的也是一个抽象的产品。

关键代码:创建过程在其子类执行。

应用实例: 1、您需要一辆汽车,可以直接从工厂里面提货,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现。 2、Hibernate 换数据库只需换方言和驱动就可以。

优点: 1、一个调用者想创建一个对象,只要知道其名称就可以了。 2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。 3、屏蔽产品的具体实现,调用者只关心产品的接口。

缺点:每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。

使用场景: 1、日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。 2、数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。 3、设计一个连接服务器的框架,需要三个协议,“POP3”、“IMAP”、“HTTP”,可以把这三个作为产品类,共同实现一个接口。

注意事项:作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。

简单工厂(静态工厂)

这里的例子借用《大话设计模式》里的那个计算器,不是刷广告哈。

这里是产品的抽象类


package com.design.factory;

public abstract class Operation {
    protected double numberA = 0;
    protected double numberB = 0;

    public abstract double getResult() throws Exception;

    public double getNumberA() {
        return numberA;
    }

    public void setNumberA(double numberA) {
        this.numberA = numberA;
    }

    public double getNumberB() {
        return numberB;
    }

    public void setNumberB(double numberB) {
        this.numberB = numberB;
    }
}

具体的子类及实现方法:

加:

package com.design.factory.impl;

import com.design.factory.Operation;

public class OperationAdd extends Operation {

    @Override
    public double getResult() {
        return numberA+numberB;
    }
}

减:

package com.design.factory.impl;

import com.design.factory.Operation;

public class OperationSub extends Operation {
    @Override
    public double getResult() {
        return numberA-numberB;
    }
}

乘:

package com.design.factory.impl;

import com.design.factory.Operation;

public class OperationMul extends Operation {
    @Override
    public double getResult() {
        return numberA*numberB;
    }
}

除:

package com.design.factory.impl;

import com.design.factory.Operation;

public class OperationDiv extends Operation {
    @Override
    public double getResult() throws Exception {
        if (numberB == 0)
            throw new Exception("除数不能为0");
        return numberA / numberB;
    }
}

具体的加减乘除实现之后,就开始咱们的工厂了。

package com.design.factory.factory;

import com.design.factory.Operation;
import com.design.factory.impl.OperationAdd;
import com.design.factory.impl.OperationDiv;
import com.design.factory.impl.OperationMul;
import com.design.factory.impl.OperationSub;

public class Factory {
    public static final int ADD = 1;
    public static final int SUB = 2;
    public static final int MUL = 3;
    public static final int DIV = 4;

    public static Operation getOperation(int operate) {
        Operation oper = null;
        switch (operate) {
            case ADD:
                oper = new OperationAdd();
                break;
            case SUB:
                oper = new OperationSub();
                break;
            case MUL:
                oper = new OperationMul();
                break;
            case DIV:
                oper = new OperationDiv();
                break;
        }
        return oper;
    }
}

最后玩都行,计算器:

 Operation operation = Factory.getOperation(Factory.ADD);
        operation.setNumberA(5);
        operation.setNumberB(6);
        System.out.println(operation.getResult());

总结:
1 它是一个具体的类,非接口,抽象类。有一个重要的create()方法,利用if或者 switch创建产品并返回。

2 create()方法通常是静态的,所以也称之为静态工厂。

缺点:
扩展性差(我想增加一种算法,除了新增一个计算类,还需要修改工厂类方法)

多方法工厂

顾名思义,多方法工厂就是有多个方法,不再使用switch或者if来判断参数,直接调用并返回你想要的对象

package com.design.factory.factory;

import com.design.factory.Operation;
import com.design.factory.impl.OperationAdd;
import com.design.factory.impl.OperationDiv;
import com.design.factory.impl.OperationMul;
import com.design.factory.impl.OperationSub;

public class Factory {

    public static Operation getAddResult() {
        return new OperationAdd();
    }

    public static Operation OperationSub() {
        return new OperationSub();
    }

    public static Operation OperationMul() {
        return new OperationMul();
    }

    public static Operation OperationDiv() {
        return new OperationDiv();
    }
}

特点:想要添加一种计算,不会修改工厂类的具体方法,而是在工厂类中添加一个static方法及添加一个继承父类的计算实现类即可

抽象工厂

顾名思义抽象工厂呢,即为要抽象工厂角色

首先我们有一个加法的接口:

package com.design.factory;

public interface OperationAdd {

    String getResult();
}

然后此接口的多个实现类:

因为懒,没有再去写别的例子,就多加了一个参数而已,勿怪勿怪

实现1:

package com.design.factory.impl;

public class OperationAdd implements com.design.factory.OperationAdd {

    @Override
    public String getResult() {
        return "Test Aperation one";
    }

}

实现2:

package com.design.factory.impl;

import com.design.factory.OperationAdd;

public class OperationAddMore implements OperationAdd {
    @Override
    public String getResult() {
        return "Test Aperation two";
    }
}

还是懒,就写这一个了,其他的都差不多。下面为抽象工厂


package com.design.factory.factory;

import com.design.factory.impl.OperationAdd;
import com.design.factory.impl.OperationDiv;
import com.design.factory.impl.OperationMul;
import com.design.factory.impl.OperationSub;

public abstract class Factory {

    public abstract OperationAdd getAddResult();

}

然后是抽象工厂的实现

实现A:

package com.design.factory.factory;

import com.design.factory.impl.OperationAdd;

public class OperationFactoryA extends Factory {
    @Override
    public OperationAdd getAddResult() {
        return new OperationAdd();
    }

}

实现B:

package com.design.factory.factory;


import com.design.factory.OperationAdd;
import com.design.factory.impl.OperationAddMore;

public class OperationFactoryB extends Factory {
    @Override
    public OperationAdd getAddResult() {
        return new OperationAddMore();
    }

}

最后,不同的工厂实现不同的产品类型。

  Factory factory1 = new OperationFactoryA();
        factory1.getAddResult();

        Factory factory2 = new OperationFactoryB();
        factory2.getAddResult();

简单的抽象工厂模式demo就写完了,类似于这种组装逻辑,抽象工厂模式还是游刃有余,如果再增加一种加法的计算方式,我们会增加一个工厂实现类,如果在增加一种计算方式(减法,乘法,除法),那么又会增加一个计算的基类以及多种计算方式的实现类,同样的功能,抽象工厂模式会有很多类文件,这就是其缺点

(反射)简单工厂模式

其他还有通过反射,Class.forName(clz.getName()).newInstance()实现的简单工厂。以及,普通的直接在工厂方法返回new 对象 的工厂。这里就不做实例讲解了,没有什么必要。

总结

工厂模式重点就是适用于 构建同产品类型(同一个接口 基类)的不同对象时,这些对象new很复杂,需要很多的参数,而这些参数中大部分都是固定的,so,懒惰的程序员便用工厂模式封装之。

(如果构建某个对象很复杂,需要很多参数,但这些参数大部分都是“不固定”的,应该使用Builder模式)

说到底,我们获得的对象仍是父类对象,工厂中的实现为子类向上转型为父类,从这里我们可以看到,子类向上转型为父类,则会遗失掉父类中没有定义的方法,而除了private的属性外,其他的属性都会被父类的属性覆盖,跑题了。

总之,为了适应程序的扩展性,拥抱变化,便衍生出了 普通工厂、抽象工厂等模式。

本文参考文献

https://www.w3cschool.cn/shejimoshi/factory-pattern.html

http://blog.youkuaiyun.com/zhangerqing/article/details/8194653

http://blog.youkuaiyun.com/zxt0601/article/details/52798423

http://blog.youkuaiyun.com/u012359453/article/details/78825270

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值