大话设计模式-策略模式

窗口展示

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阅读 211,743评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,296评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,285评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,485评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,581评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,821评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,960评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,719评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,186评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,516评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,650评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,936评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,757评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,991评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,370评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,527评论 2 349

推荐阅读更多精彩内容