【大話設計模式】第2章 商場促銷——策略模式(Java)

策略模式(Strategy):它定義了算法家族,分別封裝起來,讓他們之間能夠互相替換,此模式讓算法的變化,不會影響到使用算法的客戶。
收銀軟件類圖java

  • 聚合:表示一種弱的擁有關係,體現的是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();

                // 一、普通模式
//                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("未定義!");
//                }

                // 二、簡單工廠模式
//                CashSuper cSuper = CashFatory.createCashAccept(discount);
//                total += cSuper.getResult(price * counts);

                // 三、策略與簡單工廠結合
                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);
    }
}
相關文章
相關標籤/搜索