您当前的位置: 首页 > 

Charge8

暂无认证

  • 2浏览

    0关注

    447博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

简单工厂模式

Charge8 发布时间:2020-12-14 21:51:16 ,浏览量:2

在日常开发中,凡是需要生成复杂对象的地方,都可以尝试考虑使用工厂模式来代替。

复杂对象指的是类的构造函数参数过多等对类的构造有影响的情况,因为类的构造过于复杂,如果直接在其他业务类内使用,则两者的耦合过重,后续业务更改,就需要在任何引用该类的源代码内进行更改,光是查找所有依赖就很消耗时间了,更别说要一个一个修改了。

工厂模式的定义:

是指定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。这满足创建型模式中所要求的“创建与使用相分离”的特点。

按实际业务场景划分,工厂模式有 3 种不同的实现方式,分别是

  • 简单工厂模式
  • 工厂方法模式
  • 抽象工厂模式
一、简单工厂模式 1、简单工厂模式的定义

简单工厂模式(Simple Factory Pattern) ,又叫作静态工厂方法模式(Static Factory Method Pattern)。

我们把被创建的对象称为“产品”,把创建产品的对象称为“工厂”。如果要创建的产品不多,只要一个工厂类就可以完成,这种模式叫“简单工厂模式”。

简单来说,简单工厂模式有一个具体的工厂类,可以生成多个不同的产品,属于创建型设计模式。

简单工厂模式不在 GoF 23 种设计模式之列。

2、简单工厂模式的结构

(1)简单工厂模式主要 3个角色

  • 简单工厂(SimpleFactory): 是简单工厂模式的核心,负责实现创建所有实例的内部逻辑。工厂类的-建产品类的方法可以被外界直接调用,创建所需的产品对象。
  • 抽象产品(Product): 是简单工厂创建的所有对象的父类,负责描述所有实例共有的公共接口。
  • 具体产品(ConcreteProduct): 是简单工厂模式的创建目标。

(2)结构图如下:(图来自网络) 在这里插入图片描述

3、优缺点

主要优点:

  • 结构简单,调用方便。工厂和产品的职责区分明确。
  • 客户端无需知道所创建具体产品的类名,只需知道参数即可。

主要缺点:

  • 简单工厂模式的工厂类单一,负责所有产品的创建,职责过重,一旦异常,整个系统将受影响。且工厂类代码会非常臃肿,违背高聚合原则。
4、使用场景

对于产品种类相对较少的情况,考虑使用简单工厂模式。使用简单工厂模式的客户端只需要传入工厂类的参数,不需要关心如何创建对象的逻辑,可以很方便地创建所需产品。

5、在框架源码中使用也很广泛
  • JDK源码中的 Calendar.getInstance()方法
  • Logback源码中多个重载的 getLogger()方法
二、模式的通用实现

代码如下:

public class SimpleFactoryPattern {
    public static void main(String[] args) {
        Product product = SimpleFactory.makeProduct(2);
        product.show();
    }
    //抽象产品
    public interface Product {
        void show();
    }
    //具体产品:ProductA
    static class ConcreteProduct1 implements Product {
        @Override
        public void show() {
            System.out.println("具体产品1显示...");
        }
    }
    //具体产品:ProductB
    static class ConcreteProduct2 implements Product {
        @Override
        public void show() {
            System.out.println("具体产品2显示...");
        }
    }
    //具体产品:ProductC
    static class ConcreteProduct3 implements Product {
        @Override
        public void show() {
            System.out.println("具体产品3显示...");
        }
    }
    final class Const {
        static final int PRODUCT_A = 0;
        static final int PRODUCT_B = 1;
        static final int PRODUCT_C = 2;
    }
    static class SimpleFactory {
        public static Product makeProduct(int kind) {
            switch (kind) {
                case Const.PRODUCT_A:
                    return new ConcreteProduct1();
                case Const.PRODUCT_B:
                    return new ConcreteProduct2();
                case Const.PRODUCT_C:
                    return new ConcreteProduct3();
            }
            return null;
        }
    }
}
三、模式的应用实例

简易计算器为例,需求:输入两个数和运算符,得到结果。

1、抽象产品

public abstract class Operation {
    protected abstract double compute (double number1, double number2) throws Exception;
}

2、具体产品

  • 加法
public class OperationAdd extends Operation{
    @Override
    protected double compute(double number1, double number2) {
        return number1 + number2;
    }
}
  • 减法
public class OperationSub extends Operation{
    @Override
    protected double compute(double number1, double number2) {
        return number1 - number2;
    }
}
  • 乘法
public class OperationMul extends Operation{
    @Override
    protected double compute(double number1, double number2) {
        return number1 * number2;
    }
}
  • 除法
public class OperationDiv extends Operation{
    @Override
    protected double compute(double number1, double number2) throws Exception {
        if(number2 == 0){
            throw new Exception("除数不能为0!");
        }
        return number1 / number2;
    }
}

3、简单工厂

这里对简单工厂创建产品进行了优化,可以通过缓存、配置文件、反射和泛型等技术了优化。

如果运算业务需要扩展,需要创建具体运算类即可,不需要再修改简单工厂类了。

public class OperationFactory {

    private static final Map cachedParsers = new HashMap();

    static {
        cachedParsers.put("+", new OperationAdd());
        cachedParsers.put("-", new OperationSub());
        cachedParsers.put("*", new OperationMul());
        cachedParsers.put("/", new OperationDiv());
    }

    public static Operation createOperate0(String operate) {
        if (operate == null || operate.isEmpty()) {
            return null;//返回null还是IllegalArgumentException全凭你自己说了算
        }
        return cachedParsers.get(operate);
    }

    /**
     *  createOperate0运用缓存技术,节省内存和对象创建的时间
     *  createOperate0 和 createOperate1 同理
     */
    public static Operation createOperate1(String operate){
        Operation operation = null;
        switch (operate){
            case "+":
                operation = new OperationAdd(); break;
            case "-":
                operation = new OperationSub(); break;
            case "*":
                operation = new OperationMul(); break;
            case "/":
                operation = new OperationDiv(); break;
        }
        return operation;
    }

     /**
      * createOperate1方法不符合开闭原则
      *      如果运算业务继续扩展,需要创建具体运算类,也需要修改简单工厂的 createOperate1方法。
      * 采用反射技术进行优化,即createOperate2方法
     */
    public static Operation createOperate2(String className){
        Operation operation = null;
        try {
            if(!(null == className || "".equals(className))){
                operation = (Operation) Class.forName(className).newInstance();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return operation;
    }

    /**
     * createOperate2方法中类型强制转型,参数为字符串,可控性不高
     * 采用反射和泛型技术进行优化,即createOperate3方法
     */
    public static Operation createOperate3(Class clazz){
        try {
            if(null != clazz){
                return clazz.newInstance();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}

4、测试

public class Test {
    public static void main(String[] args) throws Exception {
        double num1 = 10;
        double num2 = 2;
        System.out.println(OperationFactory.createOperate0("*").compute(num1, num2));
        System.out.println(OperationFactory.createOperate1("*").compute(num1, num2));

        Operation operate2 = OperationFactory.createOperate2("cn.jq.learn.simplefactorypattern.OperationDiv");
        System.out.println(operate2.compute(num1, num2));

        Operation operate3 = OperationFactory.createOperate3(OperationAdd.class);
        System.out.println(operate3.compute(num1, num2));
    }
}

在这里插入图片描述

—— Stay Hungry. Stay Foolish. 求知若饥,虚心若愚。

关注
打赏
1664721914
查看更多评论
立即登录/注册

微信扫码登录

0.0514s