优化策略模式,提高账薄显示的灵活性和扩展性

接着上一篇文章,账薄显示出来之后,为了提高软件的可扩展性和灵活性,我们应用策略设计模式。这不仅仅是为了提高代码的维护性,而是因为明细分类账账薄显示的后面有金额分析这个功能,从数据库后台分析及结合Java语言特性,类似数据转置,也是软件复杂度提出的一个客观优化需求。

定义策略接口

为了软件的简易性,我们采用拖拖拉拉就可形成各种界面元素的设计方式,它虽然降低的前端开发人员的难度,可以轻松应用CSS配置文件提高视图界面的灵活性,但后台的处理多了更多的规则。大的基本结构是一个控制器中同时又镶嵌多个控制器。所以,我们定义策略模式的接口如下:

/*** 为了方便扩展,抽象显示方式,目前子类应该包括总分类账和明细分类账*/
public interface ShowZhangBen {/**** @param showZongZhangKeMu  要显示的账薄科目* @param keMuController 主科目界面的控制器* @throws IOException 由于从FXML文件加载要处理异常*/void showZhangBo(KeMu showZongZhangKeMu, KeMuController keMuController) throws IOException;}

实现基本的总分类账和明细分类账的接口实现类

当下业务需要二级科目已经满足要求,所以,我们先实现这两个策略实现类。按模式惯例,在科目主控制器中增加策略成员接口属性,然后点击科目,根据点击的科目不同,去自动的调用策略类的对应实现方式。之所以将策略做为成员属性,是因为不同的策略不光是显示方式的不同,包括后台处理和其它应该会有很多扩展类都会用引用到,所以没有从形式参数方法注入,而是从相应的策略实现类中去设置科目控制器成员属性;另一个考虑的这样做的原因是:在策略实现类中,有一次控制器重新从FXML文件加载的过程,这样加策略引用交付给主控制器,更好的体现了,子控制器不仅是一个控制器,同时是一个策略的双重角色,让主界面控制器的掌控能力更加充分。

具体的实现过程代码如下:

  /*** 显示总分类账* @return 显示面板*/@Overridepublic void showZhangBo(KeMu showZongZhangKeMu, KeMuController keMuController) throws IOException {if (showZongZhangKeMu != null && showZongZhangKeMu.getKeMuLevel().equals("1"))        //总分类账{keMuController.setStrategyShowZhangBen(new ZhangBenController());}else if (showZongZhangKeMu != null && showZongZhangKeMu.getKeMuLevel().equals("2")) {keMuController.setStrategyShowZhangBen(new MingXiZhangController());keMuController.getStrategyShowZhangBen().showZhangBo(showZongZhangKeMu,keMuController);return;}FXMLLoader loader2 = new FXMLLoader();InputStream in = ZhangBenController.class.getResourceAsStream("/zhangBen/zhangBen.fxml");loader2.setBuilderFactory(new JavaFXBuilderFactory());loader2.setLocation(ZhangBenController.class.getResource("/zhangBen/zhangBen.fxml"));AnchorPane page;try {page = (AnchorPane) loader2.load(in);keMuController.setStrategyShowZhangBen(loader2.getController());} finally {in.close();}/*** 控制器自转移*/lbeZhangbBoName=((ZhangBenController)keMuController.getStrategyShowZhangBen()).getLbeZhangbBoName();lvZongZhang=((ZhangBenController)keMuController.getStrategyShowZhangBen()).lvZongZhang;apZongZhang=((ZhangBenController)keMuController.getStrategyShowZhangBen()).apZongZhang;apZongZhangBo=((ZhangBenController)keMuController.getStrategyShowZhangBen()).apZongZhangBo;setShowKeMu(showZongZhangKeMu);lbeZhangbBoName.setText(showKeMu.getKeMuName()+"总分类账");List<ZongZhang> listData= getDataFromSpiZongZhang(showKeMu.getStrDbId());data = FXCollections.observableArrayList(listData);//给表格加上行数 2022-08-25TableColumn idCol = new TableColumn();idCol.setText("日期");idCol.setCellValueFactory(new PropertyValueFactory("recordDate"));//  idCol.setVisible(false);TableColumn taskIdCol = new TableColumn();taskIdCol.setText("凭证号数");taskIdCol.setCellValueFactory(new PropertyValueFactory("strPingZhengNo"));TableColumn costNameCol = new TableColumn();costNameCol.setText("摘要");costNameCol.setCellValueFactory(new PropertyValueFactory("strZhaiYao"));TableColumn thisAmountCol = new TableColumn();thisAmountCol.setText("√");thisAmountCol.setMinWidth(200);thisAmountCol.setCellValueFactory(new PropertyValueFactory("strCheckFlag"));TableColumn taskDateCol = new TableColumn();taskDateCol.setText("借方");taskDateCol.setMinWidth(200);taskDateCol.setCellValueFactory(new PropertyValueFactory("strJieFangAmount"));TableColumn employeeCol = new TableColumn();employeeCol.setText("贷方");employeeCol.setMinWidth(200);employeeCol.setCellValueFactory(new PropertyValueFactory("strDaiFangAmount"));TableColumn operDateCol = new TableColumn();operDateCol.setText("借或贷");operDateCol.setMinWidth(200);operDateCol.setCellValueFactory(new PropertyValueFactory("strAmountDirect"));TableColumn yuErCol = new TableColumn();operDateCol.setText("余额");operDateCol.setMinWidth(200);operDateCol.setCellValueFactory(new PropertyValueFactory("strYuAmount"));// final TableView tableView = new TableView();lvZongZhang.getColumns().clear();lvZongZhang.setItems(data);lvZongZhang.getColumns().addAll(idCol, taskIdCol, costNameCol, thisAmountCol, taskDateCol, employeeCol, operDateCol,yuErCol);apZongZhangBo.getChildren().remove(lvZongZhang);apZongZhangBo.getChildren().add(lvZongZhang);setKeMuController(keMuController);keMuController.showDetailAnchorPaneView(apZongZhangBo);}

之所以将科目层级和科目账薄类型的判断下移到策略实现类中,通过策略路由的方式去处理,为了在主界面控制器中增加新的策略时减少或没有代码的修改,虽然你增加了一点点代码,换来了主界面程序的扩展性,这可以根据自己需要决定,你认为直接在主界面中去判断然后确定策略类,这种效率更高,那也是可以的。眼下我追求的只是扩展性和健壮能性,相应的明细分类账的实现类如下:

 /*** 显示总分类账* @return 显示面板*/@Overridepublic void showZhangBo(KeMu showZongZhangKeMu, KeMuController keMuController) throws IOException {// 使用 Context 来查看当它改变策略 Strategy 时的行为变化。if (showZongZhangKeMu != null && showZongZhangKeMu.getKeMuLevel().equals("1"))        //总分类账{keMuController.setStrategyShowZhangBen(new ZhangBenController());keMuController.getStrategyShowZhangBen().showZhangBo(showZongZhangKeMu,keMuController);return;}else if (showZongZhangKeMu != null && showZongZhangKeMu.getKeMuLevel().equals("2")) {keMuController.setStrategyShowZhangBen(new MingXiZhangController());showZongZhangKeMu = keMuController.convertChooseToParentKeMu(showZongZhangKeMu);}FXMLLoader loader2 = new FXMLLoader();InputStream in = MingXiZhangController.class.getResourceAsStream("/zhangBen/mingXiZhang.fxml");loader2.setBuilderFactory(new JavaFXBuilderFactory());loader2.setLocation(MingXiZhangController.class.getResource("/zhangBen/mingXiZhang.fxml"));AnchorPane page;try {page = (AnchorPane) loader2.load(in);keMuController.setStrategyShowZhangBen(loader2.getController());} finally {in.close();}/*** 控制器自转移*/lbeZhangbBoName=((MingXiZhangController)keMuController.getStrategyShowZhangBen()).getLbeZhangbBoName();apZongZhangBo=((MingXiZhangController)keMuController.getStrategyShowZhangBen()).apZongZhangBo;lvMingXiZhang=((MingXiZhangController)keMuController.getStrategyShowZhangBen()).lvMingXiZhang;apMingXiZhang=((MingXiZhangController)keMuController.getStrategyShowZhangBen()).apMingXiZhang;setShowKeMu(showZongZhangKeMu);lbeZhangbBoName.setText(showKeMu.getKeMuName()+"明细账");List<MingXiZhang> listData= getDataFromSpiMingXiZhang(showKeMu.getStrDbId());data = FXCollections.observableArrayList(listData);//给表格加上行数 2022-08-25TableColumn idCol = new TableColumn();idCol.setText("日期");idCol.setCellValueFactory(new PropertyValueFactory("recordDate"));//  idCol.setVisible(false);TableColumn taskIdCol = new TableColumn();taskIdCol.setText("凭证号数");taskIdCol.setCellValueFactory(new PropertyValueFactory("strPingZhengNo"));TableColumn costNameCol = new TableColumn();costNameCol.setText("摘要");costNameCol.setCellValueFactory(new PropertyValueFactory("strZhaiYao"));TableColumn taskDateCol = new TableColumn();taskDateCol.setText("借方");taskDateCol.setMinWidth(200);taskDateCol.setCellValueFactory(new PropertyValueFactory("strJieFangAmount"));TableColumn daiFangCol = new TableColumn();daiFangCol.setText("贷方");daiFangCol.setMinWidth(200);daiFangCol.setCellValueFactory(new PropertyValueFactory("strDaiFangAmount"));TableColumn directCol = new TableColumn();directCol.setText("借或贷");directCol.setMinWidth(20);directCol.setCellValueFactory(new PropertyValueFactory("strAmountDirect"));TableColumn yuErCol = new TableColumn();yuErCol.setText("余额");yuErCol.setMinWidth(200);yuErCol.setCellValueFactory(new PropertyValueFactory("strYuAmount"));TableColumn[] AmountCol = new TableColumn[13];for(int i=0;i<13;i++){AmountCol[i]=new TableColumn();AmountCol[i].setText("金额分析"+String.valueOf(i+1));AmountCol[i].setMinWidth(200);AmountCol[i].setCellValueFactory(new PropertyValueFactory("amountFenXi"+String.valueOf(i+1)));}// final TableView tableView = new TableView();lvMingXiZhang.getColumns().clear();lvMingXiZhang.setItems(data);lvMingXiZhang.getColumns().addAll(idCol, taskIdCol, costNameCol, taskDateCol, daiFangCol, directCol,yuErCol);for (int i=0;i<AmountCol.length;i++){lvMingXiZhang.getColumns().add(AmountCol[i]);}apZongZhangBo.getChildren().remove(lvMingXiZhang);apZongZhangBo.getChildren().add(lvMingXiZhang);setKeMuController(keMuController);keMuController.showDetailAnchorPaneView(apZongZhangBo);}

至此,基本功能完成。

策略模式环境角色的客户端调用

        这儿策略模式环境角色的特别之处在于它本身可能是通过FXML文件加载进去的类,大概率情况如下,所以我们不用在意从构造方法中去注入策略接口去赋值,通过get和set方法是最佳途径,这儿的代码就比较简单了,不过也要注意捕捉异常,代码如下:

  @Overridepublic void changed(ObservableValue<? extends TreeItem<KeMu>> observable, TreeItem<KeMu> oldValue, TreeItem<KeMu> newValue) {System.out.println("选择的新值是:" + newValue.getValue());KeMu chooseKeMu = newValue.getValue();try {keMuController.getStrategyShowZhangBen().showZhangBo(chooseKeMu, keMuController);} catch (IOException e) {throw new RuntimeException(e);}}

完成后,运行程序,效果如下图。至此,账薄的基本显示功能完成了,这只是相当于买回来两个账薄,价值也就是二三十无人民币,大量的工作才刚刚开始,让我们逐笔开始记录吧。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/471712.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

记录一次涩涩情侣飞行棋密码破解

注本公众号&#xff0c;长期推送技术文章 知攻善防实验室 红蓝对抗&#xff0c;Web渗透测试&#xff0c;红队攻击&#xff0c;蓝队防守&#xff0c;内网渗透&#xff0c;漏洞分析&#xff0c;漏洞原理&#xff0c;开源 工具&#xff0c;社工钓鱼&#xff0c;网络安全。 81篇原…

【后端高频面试题--Nginx篇】

&#x1f680; 作者 &#xff1a;“码上有前” &#x1f680; 文章简介 &#xff1a;后端高频面试题 &#x1f680; 欢迎小伙伴们 点赞&#x1f44d;、收藏⭐、留言&#x1f4ac; 后端高频面试题--Nginx篇 往期精彩内容什么是Nginx&#xff1f;为什么要用Nginx&#xff1f;为…

「递归算法」:两两交换链表中的节点

一、题目 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09;。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4] 输出&#xf…

[力扣 Hot100]Day27 合并两个有序链表

题目描述 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 出处 思路 简单题&#xff0c;两个指针就能解决。 代码 class Solution { public:ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {if(!list1)…

Linux第55步_根文件系统第2步_测试使用busybox生成的根文件系统

测试使用busybox生成的根文件系统。测试内容较多&#xff0c;很杂。 1、修改“nfs-kernel-server” 1)、打开终端 输入“sudo vi /etc/default/nfs-kernel-server回车”&#xff0c;打开“nfs-kernel-server”文件。 输入密码“123456回车” 见下图&#xff1a; 2)、在最后…

情人节到了,写一份爱心程序(python)

前言 情人节到了&#xff0c;写一份爱心代码给喜欢的人呀 公式 首先我们介绍下爱心的公式的参数方程&#xff1a; x 16 s i n 3 ( t ) x 16sin^3(t) x16sin3(t) y 13 c o s ( t ) − 5 c o s ( 2 t ) − 2 c o s ( 3 t ) − c o s ( 4 t ) y 13cos(t) - 5cos(2t) - 2co…

Kubernetes 核心概念

一、什么是 Kubernetes 1、含义&#xff1a; Kubernetes 是一个自动化的容器编排平台&#xff0c;它负责应用的部署、应用的弹性以及应用的管理。 2、核心功能&#xff1a; (1) 调度&#xff1a; Kubernetes 的调度器可以把用户提交的容器放到 Kubernetes 管理的集群的某一…

Android Studio 实现图书借阅(管理)系统

&#x1f345;文章末尾有获取完整项目源码方式&#x1f345; 目录 前言 一、任务介绍 1.1 背景 1.2目的和意义 二、 实现介绍 视频演示 2.1 启动页实现 2.2 注册页面实现 2.3 登陆页面实现 2.4 图书列表的实现 2.5 当前借阅页面实现 2.6 我的页面实现…

京东购物拉新保姆级教程

您好&#xff0c;我是码农飞哥&#xff08;wei158556&#xff09;&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。&#x1f4aa;&#x1f3fb; 1. Python基础专栏&#xff0c;基础知识一网打尽&#xff0c;9.9元买不了吃亏&#xff0c;买不了上当。 Python从入门到精通…

Java线程与进程

线程 概念 Java中&#xff0c;线程是程序执行的最小单位&#xff0c;它是进程的一个执行流&#xff0c;也是CPU调度和分配的基本单位。每个进程都可以运行多个线程&#xff0c;这些线程共享进程的内存块&#xff0c;但每个线程都有自己的堆栈和局部变量。 Java中的线程有两种…

Jmeter接口测试实战篇:10分钟学会Jmeter的用法

一提到接口测试&#xff0c;通常大家会有这样的疑问&#xff1a;前端测试不是已经覆盖到各种业务逻辑了吗&#xff1f;为什么还要做接口测试&#xff0c;接口测试和前端测试是不是重复了&#xff1f;对于这个问题&#xff0c;可以从下面几个方面来解释&#xff1a; 什么是接口…

JS中常用占位符使用方法详解_ |%s|%d|%f|%o|%O|%c|

在 JavaScript 中&#xff0c;%s 是一种字符串格式化占位符&#xff0c;用于将字符串插入到另一个字符串中的指定位置。这种方法基于 C 语言的 printf() 函数&#xff0c;但在 JavaScript 中有一些变化。 在 JavaScript 中&#xff0c;%s 可以接受任何类型的值&#xff0c;并将…