窗口展示
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定義了一些的可供重用的算法或行為。繼承有助于析出這些算法中的公共功能
- 策略模式簡化了單元測試,每個算法都有自己的類,可以通過自己的接口單獨測試