手撕设计模式——工厂三兄弟之工厂方法

1.业务需求

​ 大家好,我是菠菜啊。在介绍这期工厂方法模式前,我们先来看看这样的需求:升级之前的计算器,增加对数和指数运算。(看这篇文章前可以先回顾《设计模式——工厂三兄弟之简单工厂》这篇)
在这里插入图片描述
在这里插入图片描述

高級計算器

2.初步实现

实现初步思路:

​ 新增运算类的子类对数和指数运算类,修改OperationFactory类,增加创建对数和指数子类判断分支。
在这里插入图片描述

OperationFactory类:

public class OperationFactory {

    public static AOpeartion createOperation(String operator){
        AOpeartion opeartion=null;
        switch (operator){
            case "+":
                opeartion=new OperationAdd();
                break;
            case "-":
                opeartion=new OperationSub();
                break;
            case "*":
                opeartion=new OperationMul();
                break;
            case "/":
                opeartion=new OperationDiv();
                break;
            case "log":
                opeartion=new OperationLog();
                break;
            case "pow":
                opeartion=new OperationPow();
                break;
        }

        return opeartion;
    }
}

​ OperationLog类:

public class OperationLog extends AOpeartion {
    @Override
    public Double getOperationResult(double numbera, double numberb) {
        return Math.log(numbera)/Math.log(numberb);
    }
}

​ OperationPow类:

public class OperationPow extends AOpeartion {
    @Override
    public Double getOperationResult(double numbera, double numberb) {
        return Math.pow(numbera,numberb);
    }
}

思考:上述代码是按照上一篇简单工厂设计模式来设计的,每增加一种运算都要修改运算工厂类,影响了原有的代码运行,违反了开闭原则**。期望新增这俩种运算不影响现有程序,并且有扩展性。那么问题出现在哪里呢?我们发现OperationFactory不够抽象,应该针对接口编程,而不是实现编程《设计模式基础——设计原则介绍》这篇的依赖倒置原则)。

3.方案改进

改造思路:

​ 新增抽象类AFactory,增加基础工厂类BasicOperationFactory、高级工厂类AdvanceOperationFactory子类,将之前的加减乘除运算子类对象的创建移动到BasicOperationFactory中,AdvanceOperationFactory中添加指数和对数运算子类对象的创建逻辑。增加OperationFactory2类,根据输入的运算符创建相应的工厂类,并且输出相应的运算子类。

在这里插入图片描述

AFactory类:

public abstract class AFactory {
    public abstract   AOpeartion createOperation(String operator);
}

BasicOperationFactory类:

public  class BasicOperationFactory extends AFactory {

    public    AOpeartion createOperation(String operator){
        AOpeartion opeartion=null;
        switch (operator){
            case "+":
                opeartion=new OperationAdd();
                break;
            case "-":
                opeartion=new OperationSub();
                break;
            case "*":
                opeartion=new OperationMul();
                break;
            case "/":
                opeartion=new OperationDiv();
                break;
            case "log":
                opeartion=new OperationLog();
                break;
            case "pow":
                opeartion=new OperationPow();
                break;
        }

        return opeartion;
    }
}

AdvanceOperationFactory类:

public  class AdvanceOperationFactory extends AFactory {

    public    AOpeartion createOperation(String operator){
        AOpeartion opeartion=null;
        switch (operator){
            case "log":
                opeartion=new OperationLog();
                break;
            case "pow":
                opeartion=new OperationPow();
                break;
        }

        return opeartion;
    }
}

OperationFactory2类:

public class OperationFactory2 {

    public static AOpeartion createOperation(String operator){
        AFactory factory=null;
        switch (operator){
            case "+":
            case "-":
            case "*":
            case "/":
                factory=new BasicOperationFactory();
                break;
            case "log":
            case "pow":
                factory=new AdvanceOperationFactory();
                break;
        }

        return factory.createOperation(operator);
    }
}

CalClient2类:

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

        Scanner sc=new Scanner(System.in);
        System.out.println("请输入第一个数:");
        double numbera=sc.nextDouble();
        System.out.println("请输入运算符:");
        String operator=sc.next();
        System.out.println("请输入第二个数:");
        double numberb=sc.nextDouble();


        AOpeartion opeartion= OperationFactory2.createOperation(operator);
        if(null!=opeartion){
            System.out.println("运算结果为:"+(opeartion.getOperationResult(numbera,numberb)));
        }else{
            System.out.println("运算工厂获取运算类失败");

        }


    }
}

思考:OperationFactory工厂类通过输入的运算符去实例化相应合适的对象,通过多态返回父类的方式实现了计算器的结果。后续如果修改具体的计算方法只要修改具体的计算类即可,不会影响其它计算类。如果增加计算方法,增加实现相应的计算类的具体子类以及增加计算工厂类的switch分支即可。需求是变化的,而且我们不可能事先就了解所有的需求,所以我们在设计的时候就要考虑后续的可扩展性、可维护性

4.定义和组成结构

工厂方法模式(FactoryMethod),定义一个创建产品对象的工厂接口,让工厂子类决定实例化那一个产品类。工厂方法使一个类的实例化延迟到其子类

我们把被创建的对象称为“产品”,把创建产品的对象称为“工厂”。工厂方法模式”是对简单工厂模式的进一步抽象化,其好处是可以使系统在不修改原来代码的情况下引进新的产品,即满足开闭原则

工厂方法模式的主要角色如下:

  • 抽象工厂(AbstractFactory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法 CreateProduct() 来创建产品。
  • 具体工厂(ConcreteFactory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建。
  • 抽象产品(AbstractProduct):定义了产品的规范,描述了产品的主要特性和功能。
  • 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。
    在这里插入图片描述

5.优缺点以及应用场景

优点:

  • 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程,延续了简单工厂创建者和使用者的分离的优点
  • 在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则
  • 高层模块只需要知道产品的抽象类,解耦,满足迪米特法则

缺点:

  • 每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度
  • 抽象产品只能生产一种产品

适用场景:

  • 使用者只知道创建产品的工厂名,而不知道具体的产品名。
  • 创建对象的任务由多个具体子工厂中的某一个完成,而抽象工厂只提供创建产品的接口。

你的收藏和点赞就是我最大的创作动力,关注我我会持续输出更新!

友情提示:请尊重作者劳动成果,如需转载本博客文章请注明出处!谢谢合作!

【作者:我爱吃菠菜 】
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值