码迷,mamicode.com
首页 > 其他好文 > 详细

面向对象的第三单元总结

时间:2019-05-21 20:53:12      阅读:176      评论:0      收藏:0      [点我收藏+]

标签:更新   需要   直接   它的   interface   伪代码   完成   graph   return   

 

(一)梳理JML语言的理论基础、应用工具链情况

梳理JML语言的理论基础

在JML官网上,是这样定义JML的。

Java建模语言(JML)是一种行为接口规范语言,可用于指定Java模块的行为 它结合了Eiffel的契约方法设计 和Larch系列接口规范语言的基于模型的规范方法 ,以及细化演算一些元素 

基础语法梳理

https://blog.csdn.net/piaopu0120/article/details/89527175

链接为我根据预习资料和第一次上课内容进行的JML语法整理,内容较多,仍放在另一个博客里。

2.应用工具链

  • Open JML:OpenJML是Java程序的程序验证工具,允许检查Java Modeling Language中注释的程序的规范;
  • JML SMT Solver:OpenJML的主流SMT Solver;
  • JML Unit:单元测试工具;
  • JMLdoc:JML规范的javadoc(jmldoc)增强版本;
  • jmlc:断言检查编译器。

(二)部署JMLUnitNG/JMLUnit,针对Graph接口的实现自动生成测试用例, 并结合规格对生成的测试用例和数据进行简要分析

(三)按照作业梳理自己的架构设计,并特别分析迭代中对架构的重构

1.第九次作业

技术图片

没有做太多架构上的设计,仅完成了目标函数的补充。在细节方面的小优化是用hashset进行去重保存节点;用hashmap实现id和Path的双重查找。

2.第十次作业

技术图片

依然没有做架构上的设计,新的图没有选择继承之前图,导致MyGraph很冗杂。主要实现了对于每一个Path的每一个小邻边的访存;修改了add和remove,完善功能;为求最短路,进行了floyd的初始化和实现。

3.第十一次作业

技术图片

 技术图片

第三次作业因为有四个相似的图,所以进行了架构上的优化。

虽然之前有考虑过指导书推荐的组合模式+工厂模式的架构,但当时主观觉得组合模式的树形结构不太好运用到这次的题(实际上是我建模的主体不对)。所以考虑了建造者模式。

建造者模式(Builder Pattern)

使用多个简单的对象一步一步构建成一个复杂的对象。

主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。

用大白话讲就是生成一个套餐。

我生成了一个floyd套餐builder和一个dij套餐builder,这两个builder可以生成各种各样的套餐。

分析:

①把问题分成由floyd算法求解更优和dijkstra算法求解更优的两类

②把floyd和dijkstra的初始化与实现拆分成小块。

③将小块进行重新组合,实现builder。

顶层组合实现举例:

 1 public Dij lessTransfer() {
 2         if (transDij == null) {
 3             transDij = new Dij();
 4             transDij.addStratege(new InitLessTransfer());
 5             transDij.addStratege(new NoneTransfer());
 6         }
 7         return transDij;
 8     }
 9 
10     public Dij lessCost() {
11         if (costDij == null) {
12             costDij = new Dij();
13             costDij.addStratege(new InitLessMoney());
14             costDij.addStratege(new Transfer2());
15         }
16         return costDij;
17     }
18 
19     public Dij lessUnplefation() {
20         if (unpleDij == null) {
21             unpleDij = new Dij();
22             unpleDij.addStratege(new InitUnstatisfication());
23             unpleDij.addStratege(new Transfer32());
24         }
25         return unpleDij;
26     }

调用builder实例:

 1 if (unpleFlag) {
 2            // 省略初始化代码
 3            // 如果没有缓存,调用builder1
 4             unpleDij = DijBuilder.getBuilder().lessUnplefation();
 5         } else {
 6             if (alreadyUnple.contains(fromNodeId)) {
 7                // 省略结果返回代码
 8             }
 9            // 如果有缓存,调用builder2
10            unpleDij = DijBuilder.getBuilder().noneunpleDij();
11         }
12         // 省略更新缓存代码
13         // 启动builder,得到结果
14         unpleDij.runDij(fromNodeId, unpleGraph, unpleExist, distict,
15             unpleNodeSort, buddy, pidMap, pathInformation);
16 }

 下面是builder的具体实现:

技术图片技术图片

以不满意度为例

DijBuilder

 1 public class DijBuilder {
 2     private Dij unpleDij = null;
 3     private Dij noneunpleDij = null;
 4 
 5     private static DijBuilder builder = new DijBuilder();
 6 
 7     private DijBuilder() {
 8     }
 9 
10     public static DijBuilder getBuilder() {
11         return builder;
12     }
13 
14     public Dij lessUnplefation() {
15         if (unpleDij == null) {
16             unpleDij = new Dij();
17             unpleDij.addStratege(new InitUnstatisfication());
18             unpleDij.addStratege(new Transfer32());
19         }
20         return unpleDij;
21     }
22 
23     public Dij noneunpleDij() {
24         if (noneunpleDij == null) {
25             noneunpleDij = new Dij();
26             noneunpleDij.addStratege(new NoneInit());
27             noneunpleDij.addStratege(new Transfer32());
28         }
29         return noneunpleDij;
30     }
31 
32 }

Dij

public class Dij {
    private List<Strategy> strategies = new ArrayList<>();

    public void addStratege(Strategy s) {
        strategies.add(s);
    }

    public void runDij(int v0, int[][] distanceGraph, boolean[][] exist,
                       HashSet<Integer> distict,
                       HashMap<Integer, Integer> nodeSort,
                       HashMap<String, Integer> buddy,
                       HashMap<Path, Integer> pidMap,
                       PathMap[] pathInformation) {
        Strategy initMethod = strategies.get(0);
        initMethod.process(0, distanceGraph, exist, distict, nodeSort,
            buddy, pidMap, pathInformation);
        Strategy calMethod = strategies.get(1);
        calMethod.process(nodeSort.get(v0), distanceGraph, exist, distict,
            nodeSort, buddy, pidMap, pathInformation);
    }
}

Strategy接口

1 public interface Strategy {
2     void process(int v0, int[][] distanceGraph, boolean[][] exist,
3                  HashSet<Integer> distict,
4                  HashMap<Integer, Integer> nodeSort,
5                  HashMap<String, Integer> buddy,
6                  HashMap<Path, Integer> pidMap, PathMap[] pathInformation);
7 }

GenerateWay抽象类实现Strategy接口,Initial抽象类类似

 1 public abstract class GenerateWay implements Strategy {
 2 
 3     public abstract void process(int v0, int[][] distanceGraph,
 4                                  boolean[][] exist,
 5                                  HashSet<Integer> distict,
 6                                  HashMap<Integer, Integer> nodeSort,
 7                                  HashMap<String, Integer> buddy,
 8                                  HashMap<Path, Integer> pidMap,
 9                                  PathMap[] pathInformation);
10 }

Transfer32类继承抽象类GenerateWay

 1 public class Transfer32 extends GenerateWay {
 2 
 3     public void process(int v0, int[][] distanceGraph, boolean[][] exist,
 4                         HashSet<Integer> distict,
 5                         HashMap<Integer, Integer> nodeSort,
 6                         HashMap<String, Integer> buddy,
 7                         HashMap<Path, Integer> pidMap,
 8                         PathMap[] pathInformation) {
 9         StaticFun.dij(v0, distict.size(), 32, distanceGraph, exist);
10     }
11 }

 

这样的方法使得在顶层实现不同的floyd或者dij的算法非常容易,可以实现n*m种任意的组合,并且不需要改动任何的底层代码。

但在实现的过程中也会遇到一些困难:

  1. 统一接口导致传参过多;

  2. 没有办法在顶层进一步封装,使得顶层代码重复变多。

 

(四)按照作业分析代码实现的bug和修复情况

1. 第九次作业

第九次作业被检测出来了一个bug,compareTO用了一种错误的方法,当时为了少些几行所以是通过差值判断的。这直接导致了溢出时判断错误。修复的时候把它修改成了大小比较。

2. 第十次作业

在判断最短路的时候忘记了两个相同点的情况,修复的时候把这个条件加上了。 

3. 第十一次作业

感谢莫策同学的数据生成器,经过很多数据的互拍让bug数减到最小。

总结

这些bug很不值得,他、它们都是很基础很容易用测试用例覆盖的问题。但这两次作业我都没怎么用心测试程序,导致了这两个bug的出现。第十一次作业我汲取了之前的教训,进行了大量的测试使得最后一次作业在强测互测都没有发现bug。以后一定谨记,在每一次测试之前优先考虑边界问题和特殊数据。

(五)阐述对规格撰写和理解上的心得体会

  • 这几次作业中,在课上我们有机会写规格,课下我们主要是通过阅读规格。但是实际上,我在课下补充一个方法时,会不根据规格来撰写代码,只是会根据规格来作为debug的一层手段。我记得在第一次作业我准备按照规格来写代码的时候,发现使用的架构和数据结构与规格表述的不太适配。
  • 在后期阅读规格的时候,比如像计算容器类的不同节点个数或者最少换乘数路径这样的题目,用语言来描述很简单,但是它的逻辑用规格来书写就非常困难。写规格的感觉对于我来说特别像写离散数学证明题,需要用非常完备的逻辑来完善我们所想表达的。
  • 一个正确的规格有助于减少歧义,规格对于方法目的的说明非常有效,因为它是贴合数据代码的,挺像伪代码对于一个问题的说明功效。
  • 规格描述了数据的变与不变,忽略了中间过程的实现,是结果指向的。

面向对象的第三单元总结

标签:更新   需要   直接   它的   interface   伪代码   完成   graph   return   

原文地址:https://www.cnblogs.com/puublog/p/10886026.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!