小菜成长记(二)--策略工厂设计模式

本文通过实例详细介绍了从简单工厂模式逐步演进到策略模式的过程,对比了不同设计模式下商品结算程序的实现方式,旨在降低代码耦合度并提高扩展性。

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

写一个商品结算程序:
public class Program {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        System.out.println("单价:");
        String numberOne = sc.next();
        System.out.println("数量:");
        String numberTwo = sc.next();
        System.out.println("打折率:");
        String rang = sc.next();

        if(!StringUtils.isNumeric(rang)){
            System.out.println("打折率输入错误");
            System.exit(0);
        }

        // 获取实际打折率
        float[] rangArr = new float[]{0,0.9f,0.8f,0.7f};
        float total = 0f;
        String rangStr = "不打折";
        try {
            switch (Integer.parseInt(rang)) {
                case 0 :
                    total = Float.parseFloat(numberOne) * Float.parseFloat(numberTwo);
                    rangStr = "不打折";
                    break;

                case 9 :
                    total = Float.parseFloat(numberOne) * Float.parseFloat(numberTwo) * rangArr[10 - Integer.parseInt(rang)];
                    rangStr = "打9折";
                    break;

                case 8 :
                    total = Float.parseFloat(numberOne) * Float.parseFloat(numberTwo) * rangArr[10 - Integer.parseInt(rang)];
                    rangStr = "打8折";
                    break;

                case 7 :
                    total = Float.parseFloat(numberOne) * Float.parseFloat(numberTwo) * rangArr[10 - Integer.parseInt(rang)];
                    rangStr = "打7折";
                    break;

                default:
                    throw new RuntimeException("不包含此种折扣");
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("输入的单价或者数量不是正数或者不包含此种折扣");
            System.exit(0);
        }
        System.out.println("总计:" + rangStr + "后 " + total);
    }
}
问题来了:“这样子增加一个算法,就更改一下代码,又不利于其他算法的保密,也不符合面向对象的三大特性”。
我:想起了上次的优化,使用简单工厂设计模式改进一次。
public class Program {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        System.out.println("单价:");
        String price = sc.next();
        System.out.println("数量:");
        String number = sc.next();
        System.out.println("打折率:");
        String rang = sc.next();

        // 获取实际打折率
        double[] rangArr = new double[]{0,0.9f,0.8f,0.7f};
        double total = 0f;
        try {
            CashSuper cash = CashFactory.createCash(rang);
            total = cash.acceptCash(Double.parseDouble(price) * Double.parseDouble(number)) ;
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("输入的单价或者数量不是正数或者不包含此种折扣");
            System.exit(0);
        }
        System.out.println("总计:" + rang + "后 " + total);
    }
}

abstract class CashSuper{
    public abstract double acceptCash(double money);
}

// 正常收费
class CashNormal extends CashSuper{
    @Override
    public double acceptCash(double money) {
        return money;
    }
}


// 打折收费
class CashRebate extends CashSuper{
    private double moneyRebate = 1l;

    public CashRebate(double moneyRebate) {
        this.moneyRebate = moneyRebate;
    }

    @Override
    public double acceptCash(double money) {
        return money * moneyRebate;
    }
}

// 满多少返利
class CashReturn extends CashSuper{
    private double moneyCondition = 0.0f;
    private double moneyReturn = 0.0f;

    public CashReturn(double moneyCondition, double moneyReturn) {
        this.moneyCondition = moneyCondition;
        this.moneyReturn = moneyReturn;
    }

    @Override
    public double acceptCash(double money) {
        double result = money;
        if(money >= moneyCondition){
            result = money - Math.floor(money/moneyCondition)*moneyReturn;
        }
        return result;
    }
}

class CashFactory {
    public static CashSuper createCash(String rang) {
        CashSuper cash = null;
        switch (rang) {
            case "不打折":
                cash = new CashNormal();
                break;

            case "打9折":
                cash = new CashRebate(0.9f);
                break;

            case "打8折":
                cash =new CashRebate(0.8f);
                break;

            case "满300送100":
                cash = new CashReturn(300,100);
                break;


            default:
                throw new RuntimeException("不包含此种折扣");
        }
        return cash;
    }
}
问题来了:“上面每增加一个算法都要更改工厂模式,重复利用代码少了,有没有更好的的设计模式呢”,最终找到了策略设计模式
public class Program {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        System.out.println("单价:");
        String price = sc.next();
        System.out.println("数量:");
        String number = sc.next();
        System.out.println("打折率:");
        String rang = sc.next();

        // 获取实际打折率
        double[] rangArr = new double[]{0,0.9f,0.8f,0.7f};
        double total = 0f;
        CashContext cash = null;
        try {
            switch (rang) {
                case "不打折":
                    cash = new CashContext(new CashNormal());
                    break;

                case "打9折":
                    cash = new CashContext(new CashRebate(0.9f));
                    break;

                case "打8折":
                    cash = new CashContext(new CashRebate(0.8f));
                    break;

                case "满300送100":
                    cash = new CashContext(new CashReturn(300, 100));
                    break;

                default:
                    throw new RuntimeException("不包含此种折扣");
            }
            total = cash.getResult(Double.parseDouble(price) * Double.parseDouble(number)) ;
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("输入的单价或者数量不是正数或者不包含此种折扣");
            System.exit(0);
        }
        System.out.println("总计:" + rang + "后 " + total);
    }
}

abstract class CashSuper{
    public abstract double acceptCash(double money);
}

// 正常收费
class CashNormal extends CashSuper{
    @Override
    public double acceptCash(double money) {
        return money;
    }
}

// 打折收费
class CashRebate extends CashSuper{
    private double moneyRebate = 1l;

    public CashRebate(double moneyRebate) {
        this.moneyRebate = moneyRebate;
    }

    @Override
    public double acceptCash(double money) {
        return money * moneyRebate;
    }
}

// 满多少返利
class CashReturn extends CashSuper{
    private double moneyCondition = 0.0f;
    private double moneyReturn = 0.0f;

    public CashReturn(double moneyCondition, double moneyReturn) {
        this.moneyCondition = moneyCondition;
        this.moneyReturn = moneyReturn;
    }

    @Override
    public double acceptCash(double money) {
        double result = money;
        if(money >= moneyCondition){
            result = money - Math.floor(money/moneyCondition)*moneyReturn;
        }
        return result;
    }
}

class CashContext{
    private CashSuper strage;
    public CashContext(CashSuper strage) {
        this.strage = strage;
    }

    public double getResult(double money){
        return strage.acceptCash(money);
    }
}
仔细看了,这不是又回到了起点,还多封装了一次。重复代码更多了。又改如何改进?
策略与简单工厂模式的结合
public class Program {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        System.out.println("单价:");
        String price = sc.next();
        System.out.println("数量:");
        String number = sc.next();
        System.out.println("打折率:");
        String rang = sc.next();

        // 获取实际打折率
        double[] rangArr = new double[]{0,0.9f,0.8f,0.7f};
        double total = 0f;
        try {
            CashContext cash = new CashContext(rang);
            total = cash.getResult(Double.parseDouble(price) * Double.parseDouble(number)) ;
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("输入的单价或者数量不是正数或者不包含此种折扣");
            System.exit(0);
        }
        System.out.println("总计:" + rang + "后 " + total);
    }
}

abstract class CashSuper{
    public abstract double acceptCash(double money);
}

// 正常收费
class CashNormal extends CashSuper{
    @Override
    public double acceptCash(double money) {
        return money;
    }
}

// 打折收费
class CashRebate extends CashSuper{
    private double moneyRebate = 1l;

    public CashRebate(double moneyRebate) {
        this.moneyRebate = moneyRebate;
    }

    @Override
    public double acceptCash(double money) {
        return money * moneyRebate;
    }
}

// 满多少返利
class CashReturn extends CashSuper{
    private double moneyCondition = 0.0f;
    private double moneyReturn = 0.0f;

    public CashReturn(double moneyCondition, double moneyReturn) {
        this.moneyCondition = moneyCondition;
        this.moneyReturn = moneyReturn;
    }

    @Override
    public double acceptCash(double money) {
        double result = money;
        if(money >= moneyCondition){
            result = money - Math.floor(money/moneyCondition)*moneyReturn;
        }
        return result;
    }
}

class CashContext{
    private CashSuper strage;
    public CashContext(String rang) {
        switch (rang) {
            case "不打折":
                strage = new CashNormal();
                break;

            case "打9折":
                strage = new CashRebate(0.9f);
                break;

            case "打8折":
                strage = new CashRebate(0.8f);
                break;

            case "满300送100":
                strage = new CashReturn(300, 100);
                break;

            default:
                throw new RuntimeException("不包含此种折扣");
        }
    }

    public double getResult(double money){
        return strage.acceptCash(money);
    }
}
简单工厂模式和策略简单工厂模式的比较
简单工厂模式 
CashSuper cash = CashFactory.createCash(rang);
total = cash.acceptCash(Double.parseDouble(price) * Double.parseDouble(number)) ;
策略工厂模式
CashContext cash = new CashContext(rang);
total = cash.getResult(Double.parseDouble(price) * Double.parseDouble(number)) ;
简单工厂模式调用者需要认识两个类,CashSuper和CashFactory,而策略工厂模式只要认识CashContext一个类。耦合程度更加降低


最后的反思:感觉策略模式用处并不是很大,只不过封装了一次,让调用者与算法分离。降低耦合度,但是代码量增多了,阅读复杂。更多等以后理解更深刻了,再补充。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值