第2章 商场促销——策略模式(Java)
策略模式(Strategy):它定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。
- 聚合:表示一种弱的拥有关系,体现的是A对象可以包含B对象,但B对象不是A对象的一部分
- 实现:继承了箭头指向的类
程序运行界面如下:
/**
* @CreateTime: 2021/02/16 16:22
* @Description: 策略模式:收银系统
*/
public class StrategyCashierSystem extends JFrame {
/** 总价 */
private static double total = 0D;
/** 满减 */
private static double sale = 0D;
public static void main(String[] args) {
// 屏幕左上角获得一个窗体
createJFramWindow();
}
public static void createJFramWindow() {
// 或者使用setTitle设置标题
JFrame jf = new JFrame("收银系统");
// 左上角位置以及宽与高
jf.setBounds(600, 300, 250, 450);
JLabel jlPrice = new JLabel("单价:");
JTextField jtfPrice = new JTextField(6);
JButton jbCertain = new JButton("确定");
JLabel jlCounts = new JLabel("数量:");
JTextField jtfCounts = new JTextField(6);
JButton jbClear = new JButton("重置");
JTextArea jtaList = new JTextArea(15, 20);
JScrollPane jspList = new JScrollPane(jtaList);
jspList.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
JLabel jlDiscount = new JLabel("折扣:");
JComboBox<String> jcbDiscount = new JComboBox<String>();
jcbDiscount.addItem("正常收费");
jcbDiscount.addItem("打9折");
jcbDiscount.addItem("每满300减100");
JLabel jlTotal = new JLabel("总计:");
JTextField jtfTotal = new JTextField(12);
jtfTotal.setText("0");
jtfTotal.setEditable(false);
jbCertain.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
// 计算当前商品总价
double price = Integer.parseInt(jtfPrice.getText());
double counts = Integer.parseInt(jtfCounts.getText());
String discount = jcbDiscount.getSelectedItem().toString();
// 1、普通模式
// switch (discount) {
// case "正常收费":
// total += price * counts;
// break;
// case "打9折":
// total += price * counts * 0.9;
// break;
// case "每满300减100":
// total += price * counts;
// sale += price * counts;
// // 每累加300就减去100,并重新累加
// if (sale >= 300) {
// sale -= 300;
// total -= 100;
// }
// break;
// default:
// System.out.println("未定义!");
// }
// 2、简单工厂模式
// CashSuper cSuper = CashFatory.createCashAccept(discount);
// total += cSuper.getResult(price * counts);
// 3、策略与简单工厂结合
CashContext cContext = new CashContext(discount);
total += cContext.getResult(price * counts);
jtfTotal.setText(String.valueOf(total));
// 列出明细
jtaList.append("单价:" + price + "\t数量:" + counts + "\t" + discount);
jtaList.append(System.lineSeparator());
}
});
jbClear.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
// 清空
jtfPrice.setText("");
jtfCounts.setText("");
jtaList.setText("");
total = 0;
sale = 0;
jtfTotal.setText("0");
}
});
// 将窗体控件添加到容器中
Container container = jf.getContentPane();
container.add(jlPrice);
container.add(jtfPrice);
container.add(jbCertain);
container.add(jlCounts);
container.add(jtfCounts);
container.add(jbClear);
container.add(jlDiscount);
container.add(jcbDiscount);
container.add(jspList);
container.add(jlTotal);
container.add(jtfTotal);
// 设定布局管理器:绝对布局
// jf.setLayout(null);
// // 相对于窗体的绝对坐标
// jlPrice.setBounds(140, 100, 200, 50);
// jbCertain.setBounds(100, 200, 200, 50);
// 设定布局管理器:流式布局
// alignment表示对齐方式:0表示左对齐,1表示居中对齐,2表示右对齐
// horizGap和vertGap分别表示不同组件之间的横向间隔和纵向间隔
jf.setLayout(new FlowLayout(1, 10, 10));
// 设定布局管理器:网格布局
// jf.setLayout(new GridLayout(6,2, 5,5));
// 设置窗体可见
jf.setVisible(true);
// 关闭时退出
jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
}
/** 现金超类 */
class CashSuper {
/**
* 现金收取超类的抽象方法
* @param money 原价
* @return 计算后的价格
*/
public double getResult(double money) {
return 0;
}
}
/** 正常收费 */
class CashNormal extends CashSuper {
@Override
public double getResult(double money) {
return money;
}
}
/** 折扣收费 */
class CashRebate extends CashSuper {
private double moneyRebate = 1D;
public CashRebate(String moneyRebate) {
this.moneyRebate = Double.valueOf(moneyRebate);
}
@Override
public double getResult(double money) {
return money * moneyRebate;
}
}
/** 满减收费 */
class CashReturn extends CashSuper {
private double moneyCondition = 0D;
private double moneyReturn = 0D;
public CashReturn(String moneyCondition, String moneyReturn) {
this.moneyCondition = Double.parseDouble(moneyCondition);
this.moneyReturn = Double.parseDouble(moneyReturn);
}
@Override
public double getResult(double money) {
double result = money;
if (money >= moneyCondition) {
// 这里计算的是对于单个商品,每满moneyCondition减moneyReturn
result = money - Math.floor(money / moneyCondition) * moneyReturn;
}
return result;
}
}
class CashFatory {
public static CashSuper createCashAccept(String type) {
CashSuper cSuper = null;
switch (type) {
case "正常收费":
cSuper = new CashNormal();
break;
case "打9折":
cSuper = new CashRebate("0.9");
break;
case "每满300减100":
cSuper = new CashReturn("300", "100");
break;
default:
System.out.println("未定义!");
}
return cSuper;
}
}
/** 用一个ConcreteStrategy来配置,维护一个对Strategy对象的引用 */
class CashContext {
private CashSuper cSuper = null;
/** 策略与简单工厂结合 */
public CashContext(String type) {
// 传入具体的收费策略
switch (type) {
case "正常收费":
cSuper = new CashNormal();
break;
case "打9折":
cSuper = new CashRebate("0.9");
break;
case "每满300减100":
cSuper = new CashReturn("300", "100");
break;
default:
System.out.println("未定义!");
}
}
/** 根据收费策略的不同,获得计算结果 */
public double getResult(double money) {
return cSuper.getResult(money);
}
}