大話設計模式-策略模式

窗口展示

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("商場收銀系統");
    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<String, CashContext> 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<String> ctxKeys() {
    return ctxMap.keySet();
  }

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

策略模式的優缺點:

  • 策略模式定義了一系列算法,這些算法功能相同,實現不同,可以采用相同的接口調用所有的算法,減少了各種算法類和適用算法類之間的耦合
  • 策略模式的Strategy類層次為Content定義了一些的可供重用的算法或行為。繼承有助于析出這些算法中的公共功能
  • 策略模式簡化了單元測試,每個算法都有自己的類,可以通過自己的接口單獨測試
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,460評論 6 538
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,067評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,467評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,468評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,184評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,582評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,616評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,794評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,343評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,096評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,291評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,863評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,513評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,941評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,190評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,026評論 3 396
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,253評論 2 375

推薦閱讀更多精彩內容