策略模式与简单工厂模式结合

文章讨论了如何在商场收费程序中合理结合策略模式和简单工厂模式,避免逻辑混乱。通过创建CashContext类,将对象创建和行为选择分离,使得程序更易维护。作者强调了两者之间的区别,简单工厂模式关注对象创建,策略模式关注行为选择并灵活切换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

策略模式与简单工厂模式结合

上文末尾,我们用策略模式去实现了商场收费程序,编写了CashContext类,虽然在分离了运算逻辑,并且在收费规则发生变化时,Context类也无需修改,但是这又回到了最初的问题,那就是在主程序中,将界面逻辑和判断应该传入什么对象给Context类的业务逻辑混在一起了,这显然无法满足程序易维护的需求

import java.util.ArrayList;
import java.util.Scanner;

/**
 * @Author yirui
 * @Date 2024/4/10 10:44
 * @Version 1.0
 */
public class AcceptCash2 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        double totalPrice = 0d;
        try {
            ArrayList<String> priceList = new ArrayList<>();
            String acceptRule;//收费规则:单价,数量,优惠方式。逗号分隔
            double price;
            int rule, count;
            while (true) {
                acceptRule = sc.nextLine();
                if (acceptRule.equals("end")) {
                    break;
                } else {
                    priceList.add(acceptRule);
                    String[] list = acceptRule.split(",");
                    price = Double.parseDouble(list[0]);
                    count = Integer.parseInt(list[1]);
                    rule = Integer.parseInt(list[2]);
                    CashContext cashContext = null;
                    switch (rule) {
                        case 1://正常收费
                            cashContext = new CashContext(new CashNormal());
                            break;
                        case 2://打八折
                            cashContext = new CashContext(new CashRebate(0.8));
                            break;
                        case 3://300-100
                            cashContext = new CashContext(new CashReturn(300,100));
                            break;
                    }
                    totalPrice += cashContext.getResult(price,count);
                }

            }
            System.out.println(totalPrice);
            System.out.println(priceList);
        } catch (Exception e) {
            System.out.println(e.toString());
        } finally {
            sc.close();
        }
    }
}

简单工厂模式与策略模式的“无效融合”方式

针对上面这个问题,我们在学习简单工厂模式的时候其实就已经知道如何去解决了,那就是创建一个工厂类,专门来负责对象的创建逻辑,在工厂类中我们可以根据用户传入的数据去判断创建什么样类型的对象。

于是我们又去写一个工厂类来负责判断需要什么类型的对象,用工厂类创建出来后把这个对象传到Context中去。如果这样的话,主程序中的代码就变成了下面这样:

import java.util.ArrayList;
import java.util.Scanner;

/**
 * @Author yirui
 * @Date 2024/4/10 10:44
 * @Version 1.0
 */
public class AcceptCash3 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        double totalPrice = 0d;
        try {
            ArrayList<String> priceList = new ArrayList<>();
            String acceptRule;//收费规则:单价,数量,优惠方式。逗号分隔
            double price;
            int rule,count;
            while (true){
                acceptRule = sc.nextLine();
                if (acceptRule.equals("end")){
                    break;
                }else {
                    priceList.add(acceptRule);
                    String[] list = acceptRule.split(",");
                    price = Double.parseDouble(list[0]);
                    count = Integer.parseInt(list[1]);
                    rule = Integer.parseInt(list[2]);
                    CashContext cashContext = null;
                    CashSuper cashAccept = CashFactory.createCashAccept(rule);
                    cashContext = new CashContext(cashAccept);
                    totalPrice += cashAccept.acceptPrice(price,count);
                }

            }
            System.out.println(totalPrice);
            System.out.println(priceList);
        }catch (Exception e){
            System.out.println(e.toString());
        }finally {
            sc.close();
        }
    }
}

看到上面这段代码大家是不是很别扭?当然别扭。经过这样一搞,原本简单工厂模式只有个工厂类,现在不仅工厂类又回来了,还多了一个Context类,这不是多此一举吗。而且我的主程序相关联的类还更多了,简单工厂模式本来只和工厂类、CashSuper类相关联,现在结合了策略模式后还和CashContext类关联上了。因此作者在文章中说了这么一句话:“难道简单工厂就一定要是一个单独的类吗?难道不可以与策略模式的Context结合?

简单工厂模式与策略模式的正确融合方式

既然工厂类生产出的类最后还是要直接传给Context类,那我们为什么不可以直接把工厂类的业务逻辑放到Context类里呢?话不多说,直接看代码:

public class CashContext1 {
    private CashSuper cashSuper;

    public CashContext1(int rule) {
        switch (rule) {
            case 1://正常收费
                cashSuper = new CashNormal();
                break;
            case 2://打八折
                cashSuper = new CashRebate(0.8);
                break;
            case 3://300-100
                cashSuper = new CashReturn(300,100);
                break;
        }
    }

    public double getResult(double price, int count) {
        return cashSuper.acceptPrice(price, count);
    }
}

改成这样之后,我们可以对比比一下他和工厂模式的区别在哪里。

public class CashFactory {
    public static CashSuper createCashAccept(int type){
        CashSuper cashSuper = null;
        switch (type){
            case 1://正常收费
                cashSuper = new CashNormal();
                break;
            case 2://打八折
                cashSuper = new CashRebate(0.8);
                break;
            case 3://300-100
                cashSuper = new CashReturn(300,100);
                break;
        }
        return cashSuper;
    }
}
  • 在工厂类中,用户传入参数,工厂类返回一个CashSuper类型的对象,主程序需要通过返回的对象来自己调用对象的方法,获得最终的结果。
  • 而在融合后的CashContext类中,CashContext类不给主程序返回对象,而是直接提供给用户一个可以调用的函数,然后主程序调用CashContext类的方法获得最终的结果。
    他们两种方式的主函数如下所示:
import java.util.ArrayList;
import java.util.Scanner;

/**
 * @Author yirui
 * @Date 2024/4/10 10:44
 * @Version 1.0
 */
public class AcceptCash {//简单工厂模式的主程序
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        double totalPrice = 0d;
        try {
            ArrayList<String> priceList = new ArrayList<>();
            String acceptRule;//收费规则:单价,数量,优惠方式。逗号分隔
            double price;
            int rule,count;
            while (true){
                acceptRule = sc.nextLine();
                if (acceptRule.equals("end")){
                    break;
                }else {
                    priceList.add(acceptRule);
                    String[] list = acceptRule.split(",");
                    price = Double.parseDouble(list[0]);
                    count = Integer.parseInt(list[1]);
                    rule = Integer.parseInt(list[2]);
                    CashSuper cashAccept = CashFactory.createCashAccept(rule);//耦合了CashSuper类和CashFactory类,当CashSuper类或者CashFactory类发生变化时有可能会影响到主程序。
                    totalPrice += cashAccept.acceptPrice(price,count);
                }

            }
            System.out.println(totalPrice);
            System.out.println(priceList);
        }catch (Exception e){
            System.out.println(e.toString());
        }finally {
            sc.close();
        }
    }
}
//
import java.util.ArrayList;
import java.util.Scanner;

/**
 * @Author yirui
 * @Date 2024/4/10 10:44
 * @Version 1.0
 */
public class AcceptCash3 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        double totalPrice = 0d;
        try {
            ArrayList<String> priceList = new ArrayList<>();
            String acceptRule;//收费规则:单价,数量,优惠方式。逗号分隔
            double price;
            int rule, count;
            while (true) {
                acceptRule = sc.nextLine();
                if (acceptRule.equals("end")) {
                    break;
                } else {
                    priceList.add(acceptRule);
                    String[] list = acceptRule.split(",");
                    price = Double.parseDouble(list[0]);
                    count = Integer.parseInt(list[1]);
                    rule = Integer.parseInt(list[2]);
                    CashContext1 cashContext = new CashContext1(rule);//只耦合了CashContext1类,CashSuper类完全分离出去了
                    totalPrice += cashContext.getResult(price,count);
                }

            }
            System.out.println(totalPrice);
            System.out.println(priceList);
        } catch (Exception e) {
            System.out.println(e.toString());
        } finally {
            sc.close();
        }
    }
}

对比上面两个主程序,虽然没有明显的差别,但是策略模式与简单工厂模式结合之后,主程序关联的类就只有CashContext类了,连CashSuper都从主程序中分离了,这样算法逻辑就彻底与页面逻辑Say goodBye了。无论后面CashSuper或者它的子类怎么变,都不会影响到页面逻辑。这就是策略模式与简单工厂模式结合的优势所在。

总结

简单工厂模式和策略模式的区别

简单工厂模式是创建型模式,它的作用是创建对象。简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建并且返回哪一个产品类(这些产品类继承自一个父类或接口)的实例。

策略模式是行为型模式,作用是在许多行为中选择一种行为,关注的是行为的多样性。策略模式是将生成实例的使用策略放在策略类中配置后才提供调用方使用。在实例化策略模式的时候已经创建好了,我们可以再策略模式中随意的拼接重写方法。

总结一下,两者的区别主要在于:
简单工厂模式关注的是对象的创建,它只负责创建具体对象。
策略模式关注的是行为的选择,它将调用方法的职责交给了Context类。

注:对于设计的学习,可能需要在不断的使用中加深对它们的理解,文章中浅显的举例可能没办法将设计模式的优点全部体现出来。

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值