窗口展示
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定义了一些的可供重用的算法或行为。继承有助于析出这些算法中的公共功能
- 策略模式简化了单元测试,每个算法都有自己的类,可以通过自己的接口单独测试