大話設(shè)計模式-策略模式

窗口展示

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.stage.Stage;

public class Main extends Application {
  private TextField priceText;
  private TextField numText;
  private ComboBox<String> switchList;

  private Button okButton;
  private Button resetButton;

  private TextArea hisText;
  private Label totalLabel;

  private double total;
  private String currentKey;

  @Override
  public void start(Stage primaryStage) throws Exception {
    primaryStage.setTitle("商場收銀系統(tǒng)");
    GridPane grid = new GridPane();
    grid.setAlignment(Pos.CENTER);
    grid.setHgap(10);
    grid.setVgap(10);
    grid.setPadding(new Insets(25, 25, 25, 25));

    int row = 0;
    priceText = new TextField();
    priceText.setAlignment(Pos.CENTER_RIGHT);
    okButton = new Button("確定");
    numText = new TextField();
    numText.setAlignment(Pos.CENTER_RIGHT);
    resetButton = new Button("重置");
    grid.add(new Label("單價:"), 0, row);
    grid.add(priceText, 1, row);
    grid.add(okButton, 2, row);

    row++;
    grid.add(new Label("數(shù)量:"), 0, row);
    grid.add(numText, 1, row);
    grid.add(resetButton, 2, row);


    switchList = new ComboBox<>();
    switchList.setEditable(true);
    switchList.setItems(FXCollections.observableArrayList(CashContext.ctxKeys()));
    switchList.getSelectionModel().select(0);
    currentKey = switchList.getSelectionModel().getSelectedItem().toString();
    row++;
    grid.add(new Label("策略:"), 0, row);
    grid.add(switchList, 1, row);

    hisText = new TextArea();
    row++;
    grid.add(hisText, 0, row, 10, 4);

    totalLabel = new Label("0.0");
    totalLabel.setTextFill(Color.FIREBRICK);
    totalLabel.setAlignment(Pos.CENTER);
    totalLabel.setFont(Font.font("Tahoma", FontWeight.NORMAL, 20));
    HBox hbBtn = new HBox(10);
    hbBtn.setAlignment(Pos.BOTTOM_RIGHT);
    hbBtn.getChildren().add(totalLabel);
    row += 4;
    grid.add(new Label("總計:"), 0, row);
    grid.add(hbBtn, 1, row);
    listen();
    Scene scene = new Scene(grid, 450, 300);
    primaryStage.setScene(scene);
    primaryStage.show();
  }

  private void listen() {
      switchList.setOnAction(ev -> currentKey = switchList.getSelectionModel().getSelectedItem().toString());
      okButton.setOnAction(e -> {
      double price = Double.parseDouble(priceText.getText());
      double num = Double.parseDouble(numText.getText());
      CashContext cashContext = CashContext.getCashContext(currentKey);
      double current = cashContext.getResult(price * num);
      total += current;
      hisText.appendText(String.format("單價:%.2f ,數(shù)量:%.2f ,策略: %s, 當(dāng)前:%.2f ,總計:%.2f %n", price, num, currentKey, current, total));
      totalLabel.setText(String.format("%.2f", total));
    });
    resetButton.setOnAction(e -> {
      total = 0;
      hisText.clear();
      priceText.setText("");
      numText.setText("");
      totalLabel.setText(String.format("%.2f", total));
    });
  }

  public static void main(String[] args) {
    launch(args);
  }
}

策略模式的金額計算

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

public class CashContext {
  private final CashSuper cashSuper;

  public CashContext(CashSuper cashSuper) {
    this.cashSuper = cashSuper;
  }

  public double getResult(double money) {
    return cashSuper.acceptCash(money);
  }

  // 現(xiàn)金收費(fèi)接口
  public interface CashSuper {
    double acceptCash(double money);
  }

  // 正常收費(fèi)子類
  public static class CashNormal implements CashSuper {

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

  // 滿減收費(fèi)子類
  public static class CashReturn implements CashSuper {
    private final double condMoney;
    private final double returnMoney;

    public CashReturn(double condMoney, double returnMoney) {
      this.condMoney = condMoney;
      this.returnMoney = returnMoney;
    }

    @Override
    public double acceptCash(double money) {
      if (money > condMoney) {
        return money - returnMoney;
      }
      return money;
    }
  }

  // 打折收費(fèi)子類
  public static class CashRebate implements CashSuper {
    private double rebate;

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

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

  // 工廠相關(guān)實(shí)現(xiàn)
  private static final Map<String, CashContext> ctxMap = new LinkedHashMap<>();

  static {
    // 注冊收費(fèi)策略
    ctxMap.put("正常收費(fèi)", new CashContext(new CashNormal()));
    ctxMap.put("滿300返100", new CashContext(new CashReturn(300, 100)));
    ctxMap.put("打8折", new CashContext(new CashRebate(0.8)));
  }

  public static Set<String> ctxKeys() {
    return ctxMap.keySet();
  }

  public static CashContext getCashContext(String currentKey) {
    return ctxMap.get(currentKey);
  }
}

策略模式的優(yōu)缺點(diǎn):

  • 策略模式定義了一系列算法,這些算法功能相同,實(shí)現(xiàn)不同,可以采用相同的接口調(diào)用所有的算法,減少了各種算法類和適用算法類之間的耦合
  • 策略模式的Strategy類層次為Content定義了一些的可供重用的算法或行為。繼承有助于析出這些算法中的公共功能
  • 策略模式簡化了單元測試,每個算法都有自己的類,可以通過自己的接口單獨(dú)測試
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容