大话设计模式-策略模式

大话设计模式-策略模式_第1张图片

窗口展示

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 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("商场收银系统");
    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("数量:"), 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 ,数量:%.2f ,策略: %s, 当前:%.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);
  }

  // 现金收费接口
  public interface CashSuper {
    double acceptCash(double money);
  }

  // 正常收费子类
  public static class CashNormal implements CashSuper {

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

  // 满减收费子类
  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;
    }
  }

  // 打折收费子类
  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;
    }
  }

  // 工厂相关实现
  private static final Map ctxMap = new LinkedHashMap<>();

  static {
    // 注册收费策略
    ctxMap.put("正常收费", 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 ctxKeys() {
    return ctxMap.keySet();
  }

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

策略模式的优缺点:

  • 策略模式定义了一系列算法,这些算法功能相同,实现不同,可以采用相同的接口调用所有的算法,减少了各种算法类和适用算法类之间的耦合
  • 策略模式的Strategy类层次为Content定义了一些的可供重用的算法或行为。继承有助于析出这些算法中的公共功能
  • 策略模式简化了单元测试,每个算法都有自己的类,可以通过自己的接口单独测试

你可能感兴趣的:(大话设计模式-策略模式)