首页 > 编程语言 >《大话设计模式》java实现:第二章-策略模式

《大话设计模式》java实现:第二章-策略模式

时间:2024-10-26 17:32:12浏览次数:1  
标签:java double 大话 getDiscount discount frame new 设计模式 sum

《大话设计模式》java实现:第二章-策略模式

第二章是使用策略模式实现商场收银系统,使收银系统的促销策略可以灵活更改。

1. 原始代码实现:

package gof;

/*
 * 《大话设计模式》第二章策略模式
 * 实现商场收银系统,可以选择不同促销策略
 */

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class StrategyPattern {
    public static void main(String[] args) {
        new Gui();
    }
}

// 收银系统UI
class Gui {
    private JFrame frame;
    private JTextField numberField;
    private JTextField priceField;
    private JComboBox<String> discountBox;
    private JLabel resultLabel;

    public Gui() {
        frame = new JFrame("商场收银系统");
        frame.setSize(400, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new GridLayout(5, 2));

        // 输入商品数量
        JLabel numberLabel = new JLabel("商品数量:");
        numberField = new JTextField();
        frame.add(numberLabel);
        frame.add(numberField);

        // 输入商品单价
        JLabel priceLabel = new JLabel("商品单价:");
        priceField = new JTextField();
        frame.add(priceLabel);
        frame.add(priceField);

        // 选择折扣方式
        JLabel discountLabel = new JLabel("折扣方式:");
        discountBox = new JComboBox<>(new String[]{"无折扣", "打八折", "满二十减五"});
        frame.add(discountLabel);
        frame.add(discountBox);

        // 计算按钮
        JButton calcButton = new JButton("计算");
        calcButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                calculate();
            }
        });
        frame.add(calcButton);

        // 显示结果
        resultLabel = new JLabel("总计: 0.0");
        frame.add(resultLabel);

        frame.setVisible(true);
    }

    //计算函数
    private void calculate() {
        try {
            double number = Double.parseDouble(numberField.getText());
            double price = Double.parseDouble(priceField.getText());
            String discount = (String) discountBox.getSelectedItem();

            //调用计算类的计算函数
            double result=SimpleCount.getCount(number, price, discount);
            resultLabel.setText("总计: " + result);
        } catch (NumberFormatException e) {
            resultLabel.setText("输入错误!");
        }
    }
}

// 商品价格结算类,最原始的实现。
class SimpleCount {
    static double getCount(double number, double price, String discount) {
        double sum = number * price;
        // 打折
        switch (discount) {
            case "无折扣": {
                return sum;
            }
            case "打八折": {
                return sum * 0.8;
            }
            case "满二十减五": {
                return sum >=20 ? sum - 5 : sum;
            }
            default:
                throw new IllegalArgumentException("Unexpected value: " + discount);
        }
    }
}

在这个原始类中,每次更改促销策略都需要修改计算类和GUI,十分不方便。

简单工厂实现

为了节省篇幅,仅贴出需要修改的calculate()函数和其它类

private void calculate() {
        try {
            double number = Double.parseDouble(numberField.getText());
            double price = Double.parseDouble(priceField.getText());
            String discountString = (String) discountBox.getSelectedItem();
            
            //调用折扣工厂初始化折扣类,调用折扣类获取打折后的价格
            double sum=number*price;
            Discount discount=DiscountFactory.getDiscount(sum, discountString);
            double result=discount.getDiscount();

            resultLabel.setText("总计: " + result);
        } catch (NumberFormatException e) {
            resultLabel.setText("输入错误!");
        }
    }
// 抽象打折类
abstract class Discount {
    double sum;
    abstract double getDiscount();
}

class NoDiscount extends Discount {
    @Override
    double getDiscount() {
        return sum;
    }
}

class P8Discount extends Discount {
    @Override
    double getDiscount() {
        return sum * 0.8;
    }
}

class Return5Discount extends Discount {
    @Override
    double getDiscount() {
        return sum >= 20 ? sum - 5 : sum;
    }
}

// 打折类工厂
class DiscountFactory {
    static Discount getDiscount(double sum, String discountString) {
        Discount discount;

        switch (discountString) {
            case "无折扣": {
                discount = new NoDiscount();
                break;
            }
            case "打八折": {
                discount = new P8Discount();
                break;
            }
            case "满二十减五": {
                discount = new Return5Discount();
                break;
            }
            default:
                throw new IllegalArgumentException("Unexpected value: " + discountString);
        }

        // 在最后给成员变量赋值,避免写出多个赋值语句
        discount.sum = sum;
        return discount;
    }
}

每次更改促销策略仍然需要修改计算类和GUI,十分不方便。

原始策略模式实现

删去了工厂,在计算函数中进行计算策略的实例化:

private void calculate() {
        try {
            double number = Double.parseDouble(numberField.getText());
            double price = Double.parseDouble(priceField.getText());
            String discountString = (String) discountBox.getSelectedItem();
            
            Discount discount;
            //实例化discount
            switch (discountString){
            case "无折扣": {
                discount = new NoDiscount();
                break;
            }
            case "打八折": {
                discount = new P8Discount();
                break;
            }
            case "满二十减五": {
                discount = new Return5Discount();
                break;
            }
			default:
				throw new IllegalArgumentException("Unexpected value: " + discountString);
			}
            discount.sum=number*price;
            //调用上下文获取折后价
            DiscountContext discountContext=new DiscountContext(discount);
            double result=discountContext.getDiscount();

            resultLabel.setText("总计: " + result);
        } catch (NumberFormatException e) {
            resultLabel.setText("输入错误!");
        }
    }

新增了一个策略上下文类:

// 抽象打折类
abstract class Discount {
    double sum;
    abstract double getDiscount();
}

class NoDiscount extends Discount {
    @Override
    double getDiscount() {
        return sum;
    }
}

class P8Discount extends Discount {
    @Override
    double getDiscount() {
        return sum * 0.8;
    }
}

class Return5Discount extends Discount {
    @Override
    double getDiscount() {
        return sum >= 20 ? sum - 5 : sum;
    }
}

//使用原始策略模式
class DiscountContext{
	private Discount discountClass;
	
	//构造时传入具体折扣策略类
	public DiscountContext(Discount discountSuper) {
		this.discountClass=discountSuper;
	}
	
	//调用策略类的方法得到值。
	public double getDiscount() {
		return discountClass.getDiscount();
	}
}

这样一来,在客户端实例化算法类,如果需要修改算法类,就需要修改客户端的实例化代码。还是很不方便。

策略模式+简单工厂实现

将工厂模式和策略模式上下文结合,在策略模式上下文中实例化算法类。

修改calculate函数:

private void calculate() {
    try {
        double number = Double.parseDouble(numberField.getText());
        double price = Double.parseDouble(priceField.getText());
        String discountString = (String) discountBox.getSelectedItem();
        
        //调用上下文获取折后价
        DiscountContext discountContext=new DiscountContext(number, price, discountString);
        double result=discountContext.getDiscount();

        resultLabel.setText("总计: " + result);
    } catch (NumberFormatException e) {
        resultLabel.setText("输入错误!");
    }
}

在DiscountContxt类增加实例化语句:

//策略模式与简单工厂模式组合
class DiscountContext{
	private Discount discount;
	
	//构造函数与简单工厂结合
	public DiscountContext(double number, double price, String discountString) {
		switch (discountString) {
        case "无折扣": {
            discount = new NoDiscount();
            break;
        }
        case "打八折": {
            discount = new P8Discount();
            break;
        }
        case "满二十减五": {
            discount = new Return5Discount();
            break;
        }
        default:
            throw new IllegalArgumentException("Unexpected value: " + discountString);
    }

		// 在最后给成员变量赋值,避免写出多个赋值语句
		discount.sum = number*price;
	}
	
	//调用策略类的方法得到值。
	public double getDiscount() {
		return discount.getDiscount();
	}
}

这种设计模式比上面几种更加清楚。GUI的计算函数调用上下文,算法的实例化和计算都由上下文来调用。这样GUI只依赖于上下文类。
与简单工厂的区别就在于简单工厂中,GUI的计算函数需要调用工厂类和算法类两个类,而策略模式+简单工厂只需要调用上下文类,进一步降低了耦合。

下面附上完全体代码:

package gof;

/*
 * 《大话设计模式》第二章策略模式
 * 实现商场收银系统,可以选择不同促销策略
 */

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class StrategyPattern {
    public static void main(String[] args) {
        new Gui();
    }
}

// 收银系统UI
class Gui {
    private JFrame frame;
    private JTextField numberField;
    private JTextField priceField;
    private JComboBox<String> discountBox;
    private JLabel resultLabel;

    public Gui() {
        frame = new JFrame("商场收银系统");
        frame.setSize(400, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new GridLayout(5, 2));

        // 输入商品数量
        JLabel numberLabel = new JLabel("商品数量:");
        numberField = new JTextField();
        frame.add(numberLabel);
        frame.add(numberField);

        // 输入商品单价
        JLabel priceLabel = new JLabel("商品单价:");
        priceField = new JTextField();
        frame.add(priceLabel);
        frame.add(priceField);

        // 选择折扣方式
        JLabel discountLabel = new JLabel("折扣方式:");
        discountBox = new JComboBox<>(new String[]{"无折扣", "打八折", "满二十减五"});
        frame.add(discountLabel);
        frame.add(discountBox);

        // 计算按钮
        JButton calcButton = new JButton("计算");
        calcButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                calculate();
            }
        });
        frame.add(calcButton);

        // 显示结果
        resultLabel = new JLabel("总计: 0.0");
        frame.add(resultLabel);

        frame.setVisible(true);
    }

    private void calculate() {
        try {
            double number = Double.parseDouble(numberField.getText());
            double price = Double.parseDouble(priceField.getText());
            String discountString = (String) discountBox.getSelectedItem();
            
            //调用上下文获取折后价
            DiscountContext discountContext=new DiscountContext(number, price, discountString);
            double result=discountContext.getDiscount();

            resultLabel.setText("总计: " + result);
        } catch (NumberFormatException e) {
            resultLabel.setText("输入错误!");
        }
    }
}

// 抽象打折类
abstract class Discount {
    double sum;
    abstract double getDiscount();
}

class NoDiscount extends Discount {
    @Override
    double getDiscount() {
        return sum;
    }
}

class P8Discount extends Discount {
    @Override
    double getDiscount() {
        return sum * 0.8;
    }
}

class Return5Discount extends Discount {
    @Override
    double getDiscount() {
        return sum >= 20 ? sum - 5 : sum;
    }
}

//策略模式与简单工厂模式组合
class DiscountContext{
	private Discount discount;
	
	//构造函数与简单工厂结合
	public DiscountContext(double number, double price, String discountString) {
		switch (discountString) {
        case "无折扣": {
            discount = new NoDiscount();
            break;
        }
        case "打八折": {
            discount = new P8Discount();
            break;
        }
        case "满二十减五": {
            discount = new Return5Discount();
            break;
        }
        default:
            throw new IllegalArgumentException("Unexpected value: " + discountString);
    }

		// 在最后给成员变量赋值,避免写出多个赋值语句
		discount.sum = number*price;
	}
	
	//调用策略类的方法得到值。
	public double getDiscount() {
		return discount.getDiscount();
	}
}

标签:java,double,大话,getDiscount,discount,frame,new,设计模式,sum
From: https://www.cnblogs.com/save-mw/p/18504250

相关文章

  • 【源码+论文】Java毕业设计:基于SpringBoot协同过滤算法的汽车推荐网站(Mysql数据库)
    ✅更多源码|课设......
  • gdal部署及java调用详细过程(linux版本-ubuntu)
    建议gdal用3.5.3前的版本,因为目前网上大部分文章都是适用这个版本之前的编译方法一、gdal部署1)安装gcc通过系统包管理器安装sudoaptinstallgccgcc--version2)安装g++通过系统包管理器安装sudoaptinstallg++g++--version3)安装Ant通过系统包管理器安装sudoapt-g......
  • 三高应用的设计原则 java 三高
    高并发负载均衡:通过负载均衡器来分配请求到多个服务器或实例,避免单点过载。异步处理:采用异步非阻塞的方式处理任务,减少等待时间,提高资源利用率。无状态设计:确保服务实例之间无状态依赖,这样任何实例都可以处理任何请求,便于扩展。缓存策略:合理利用缓存减少数据库访问压力,提高......
  • vue3+java+springboot在线考试系统(08169)
    目录功能介绍具体实现截图技术介绍开发核心技术介绍:技术创新点vue3和vue2的区别:核心代码部分展示非功能需求分析系统开发流程软件测试源码获取功能介绍随着社会的发展,系统的管理形势越来越严峻。越来越多的用户利用互联网获得信息,但各种信息鱼龙混杂,信息真假难以辨......
  • java的无锁编程和锁机制
    Java的并发编程中,为了保证线程安全和高性能,采用了两种主要的同步手段:锁机制和无锁编程。以下是对锁机制、无锁编程、死锁及其避免的详细讲解。一、无锁编程无锁编程通过原子操作来避免传统锁,从而减少线程的上下文切换,提升性能。在Java中,通常使用java.util.concurrent.......
  • Java 中 & 和 && 以及 | 和 || 的区别
    在Java中,&和&&以及|和||都是逻辑运算符,但它们在使用上有一些重要的区别。以下是对这些运算符的全面总结,包括它们的区别、应用场景和代码示例。1.&和&&&:按位与运算符:当作用于整数类型时,它执行按位与操作。逻辑与运算符:当作用于布尔类型时,它会计算两边的......
  • Java 题目集总结
    一、前言在本次Java课程的学习中,我们通过完成三次精心设计的题目集,深入探索了Java编程的广阔世界。这三次题目集犹如攀登知识高峰的阶梯,每一次都引领我们迈向更高的层次,涵盖了从基础概念到复杂应用的多个重要知识点,为我们提供了宝贵的实践机会,使我们在编程的道路上不断成长和......
  • java+vue计算机毕设动物救助微信小程序【开题+程序+论文+源码】
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景在当今社会,随着城市化进程的加速和人们生活方式的变化,流浪动物问题日益凸显。大量无家可归的动物在街头巷尾流浪,面临着饥饿、疾病、意外伤害等多重困......
  • java+vue计算机毕设饭店订餐系统【开题+程序+论文+源码】
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着信息技术的迅猛发展和消费者需求的日益多样化,餐饮行业正面临着前所未有的变革。传统的饭店订餐方式,如电话预订或到店点餐,已难以满足现代顾客对于......
  • java+vue计算机毕设纯音乐播放网站【开题+程序+论文+源码】
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着互联网技术的飞速发展,音乐已成为人们日常生活中不可或缺的一部分。纯音乐,以其独特的旋律和氛围,不仅能够舒缓压力、激发灵感,还能在特定情境下营造......