设计模式4——工厂方法模式

写文章的初心主要是用来帮助自己快速的回忆这个模式该怎么用,主要是下面的UML图可以起到大作用,在你学习过一遍以后可能会遗忘,忘记了不要紧,只要看一眼UML图就能想起来了。同时也请大家多多指教。

工厂方法模式(Factory Method)

是一种创建型模式。

目录

一、概述

二、使用过程

三,举例 


一、概述

1、定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
2、和简单工厂模式不同的是,新建多个不同的工厂,用不同的方式去创建对象。使得我们有更多个性化创建对象的选择。

 主要的角色分两种,实现起来的话(为了充分使用面向对象语言的3大特性,还另外需要抽象类或接口)有4个:

  • 工厂的抽象类(单个) + 工厂的实现类(多个):控制创建哪些对象的类
  • 产品的抽象类(单个) + 产品实现类(多个):那些需要被创建(实例化)的类 

 理论上这些角色之间的关系如下:

 

 通过技术实现的角度看,对象之间关系的UML图如下:

(提示:在Java中,对于工厂在创建对象的过程上,引入反射和配置文件等技术,可以使程序更加灵活。)

二、使用过程

  步骤如下:

 1、现实遇到的问题:

  • 当我们需要使用不同的方式去创建不同的对象实例时(注:有时候也需要我们先去分析或抽象出那些想要被创建的对象是不是属于同一种类型,如果分析不出来也可以只定义它们的父类为一个空的类)。

2、针对问题的设计要素:

  • 一个被需要创建地对象的抽象类或接口:用来定义被创建对象的公共约束或超类;
  •  一个工厂的抽象类或接口:用来创建某一类型的对象的公共约束或超类;
  • 其他具体的工厂类、产品类等;
  • 有时候为了方便可能会需要有创建工厂的工厂。

三,举例 

3.1、实现一个计算器,分析步骤:

1、现实遇到的问题:

  • 为了实现计算器,我们经常需要的运算对象有:如加法运算、减法运算、除法运算、乘法运算,除此之外还有指数运算、对数运算等。

1.1、思考发现:

        运算类包括:加法、减法、除法、乘法它们都为简单运算,指数运算、对数运算都为其他类型运算。那么我们的工厂也就可以分为基本运算工厂,和其他运算工厂。当然也需要一个综合工厂去控制运算工厂实例的创建

2、针对问题的设计要素:

  • 一个工厂抽象类或接口;
  • 一个运算抽象类或接口;
  • 各种具体地专门创建运算对象的工厂;
  • 各种具体的运算类,如:加法、减法、除法、乘法等;
  • 一个用来创建不同工厂的工厂对象。

 3.2、对象之间的关系用UML图表示如下:

 3.3、Java实现代码如下(建议你在本地试一下,加深印象):

运算类接口(也可以根据需要为抽象类):

public interface Operation {
    public double getResult(double num1, double num2);
}

加法:

public class Add implements Operation {
    @Override
    public double getResult(double num1, double num2) {
        return num1 + num2;
    }
}

减法:

public class Sub implements Operation {
    @Override
    public double getResult(double num1, double num2) {
        return num1 - num2;
    }
}

除法:

public class Div implements Operation {
    @Override
    public double getResult(double num1, double num2) {
        if (num2 == 0) {
            throw new ArithmeticException("除数不能为零!");
        }
        return num1 / num2;
    }
}

乘法:

public class Mul implements Operation {
    @Override
    public double getResult(double num1, double num2) {
        return num1 * num2;
    }
}

指数运算:

public class Pow implements Operation {
    @Override
    public double getResult(double num1, double num2) {
        return Math.pow(num1, num2);
    }
}

对数运算:

public class Log implements Operation {
    @Override
    public double getResult(double num1, double num2) {
        return Math.log(num2) / Math.log(num1);
    }
}

 工厂接口(也可以根据需要为抽象类):

public interface IFactory {
    public Operation createOperation(String operate);
}

基本运算工厂:

public class BasicOperationFactory implements IFactory {
    @Override
    public Operation createOperation(String operate) {
        Operation operation = null;
        switch (operate) {
            case "+":
                operation = new Add();
                break;
            case "-":
                operation = new Sub();
                break;
            case "*":
                operation = new Mul();
                break;
            case "/":
                operation = new Div();
                break;
        }
        return operation;
    }
}

其他运算工厂:

public class OtherOperationFactory implements IFactory {
    @Override
    public Operation createOperation(String operate) {
        Operation operation = null;
        switch (operate) {
            case "pow":
                operation = new Pow();
                break;
            case "log":
                operation = new Log();
                break;
        }
        return operation;
    }
}

 综合工厂类:

public class OperationFactory {
    public Operation createOperate(String operate) {
        Operation operation;
        IFactory factory = null;
        switch (operate) {
            case "+":
            case "-":
            case "*":
            case "/":
                factory = new BasicOperationFactory();
                break;
            case "pow":
            case "log":
                factory = new OtherOperationFactory();
                break;
        }
        operation = factory.createOperation(operate);
        return operation;
    }
}

主程序(发起请求的类):

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入被运算数:");
        double num1 = Double.parseDouble(scanner.nextLine());
        System.out.print("请输入运算符号:");
        String operate = scanner.nextLine();
        System.out.print("请输入运算数:");
        double num2 = Double.parseDouble(scanner.nextLine());
        Operation operation = new OperationFactory().createOperate(operate);
        System.out.print("结果为:" + operation.getResult(num1, num2));
    }
}

小说明:运算符号可输入,加+、减-、乘*、除/、指数运算pow、对数运算log;运算数可以输入double类型数据。

就不再举例了,可以把上面的Java例子复制到你本地,运行main函数试一下加深理解。这些代码都是我自己学习的时候根据一些教材手敲的,不存在bug可以直接运行。

本例子借鉴的教材是《大话设计模式》。

  • 22
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值