关于物流的5种模型10种算法的实现

整个设计涉及5个游戏2种类型,分别为
l        路径图形相关
a)      最短路径
b)      物流中心选址
c)      最优路径
l        表格相关
a)      单周期模型
                    i.              最大利润模型
                ii.              最小损失模型
b)      预测
                    i.              直线预测,
                ii.              二次抛物线预测
            iii.              指数平滑法
                iv.              回归分析法
                    v.              趋势平均数法
5个游戏10个算法在调研、学习、分析并理解算法的基础上,经过不懈的努力和编程测试使用java实现的。算法的介绍在各个游戏的说明中有相关文档,内容枯燥晦涩难懂,在这里不作介绍。在设计界面的过程中,综合考虑所有的算法,把算法的表现形式分为两个大类,图形路径相关和表格相关。图形路径相关的界面程序的基本需求就是:根据用户在界面上画出的城市节点和路径信息计算出一个最优化的结果。表格相关的基本需求是:根据用户在表格中输入的数据产生出一个最终的结果,结果是一个数字。根据以上的两个基本需求,下面逐一介绍界面设计的过程。
    图形路径相关的界面需要能接纳并处理用户的操作,用户的操作包括:在可视化的面板上画出城市节点,修改城市节点的基本信息:城市名字和权重,在城市与城市之间需要连线,代表城市之间的距离;距离的大小根据需要进行调整,删除错误的路径,删除错误的城市节点,计算结果,查看计算的结果,保存图形,打开已经保存过的图形,退出程序,查看程序的介绍和说明。在以上的需求中,比较困难也比较核心的需求就是画出城市节点和连线。使用Swing作为画图的程序有许多可用的插件,但是作者使用JBuilder或者其他的做图(GUI)程序需要学习的时间,生成的代码页并不总是很理想。所以作者决定一行行的写代码,这样对程序有完全的掌控。整个设计分为以下的几个部分关于物流的5种模型10种算法的实现

所有的图形元素都必须实现IElement接口,在IElement接口中定义了图形元素的通用操作,他们是标准的Getset方法,主要的getset方法有:前景色,背景色,元素名称(用于保存和打开以及构建元素原型),元素的具体类型(用于打开),画笔粗细等,以及一些方法:画图方法,被选中状态的画图方式,元素的中心位置(拖拽操作使用),是否包含某个点的位置(用于决定元素是否可以被选中),属性对话框操作,图形元素显示的优先级(用于在点击图形叠加的位置时,决定哪个元素被选中),本次设计中由于不需要多种点的类型,所以只设计了两种元素,一种为点CityNode,另一种为线,Path,代表两个城市之间的路径。使用者可以根据需要在面板上画出所有需要的城市节点和节点之间的连线,设置城市节点的属性名字和权重,设置路径的长度,所有这些操作都可以通过快捷键、工具条、菜单栏或者右键进行操作。游戏提供了保存和打开的功能,用于存储界面上的元素。在内部组织中使用一个List对象缓存所有的界面元素,保存和打开都操作这个对象。在进行计算的过程中,也需要传输这个对象到适配器对象,由适配器进行过滤抽取操作。
    算法的设计:算法的设计独立于图形界面元素的开发,无论从开发时间还是考虑到扩展性都语图形界面元素没有太大的关系。因此算法的开发就需要考虑不同情况的应用。根据OOP的指导思想:对于每个算法 ,首先设计其通用的接口,接口方法尽量简单,其次设计抽象类,实现接口中的通用方法,每个具体类的算法都扩展自抽象类。再次设计测试类,针对接口进行测试。在经过若干天或者由不同的人来调用该类只用重新温习一下测试程序即可。在这一点上,即使是自己开发的程序接口,过个一周之后再次回头看这个程序,也需要测试程序的帮忙。
下面是预测的类图:
关于物流的5种模型10种算法的实现
预测的返回结果是一个数字,因此可以使用一个接口:下面是针对接口的测试例子:
public class TestLineForetell extends BaseTestCase {
    public TestLineForetell(String method) {
       super(method);
    }
    public void testAoyunGold() {
       IForeTell f = new LineForeTell();
       f.setNum(6);
       f.setData(1, 15);
       f.setData(2, 5);
       f.setData(3, 16);
       f.setData(4, 16);
       f.setData(5, 28);
       f.setData(6, 32);
       f.setWillTime(7);
       log.debug("ForTell AoyunGold:" + f.getForetellData());
    }
    public static Test suite() {
       TestSuite suite = new TestSuite();
        suite.addTest(new TestLineForetell("testAoyunGold"));
       return suite;
    }
}
适配器的设计:当界面程序和算法程序已经设计完毕,就需要一个适配器来把界面元素的信息转换成算法能识别的信息,经过算法的计算,适配器在把计算的结果转换成界面程序可以识别的信息,并表现出来。适配器没有固定的接口,主要是因为不同类型的算法计算的结果类型不完全一样,比如路径的计算结果可能是多个数组,而预测计算的结果仅仅是一个数字。下面是关于预测的一个适配器:package com.logis.game.adapter.foretell;
public class ForetellAdapter {
    private IForeTell foretell;
    private List<DataRow> data;
 
    public double doWork(String willTime) {
        for (DataRow dRow : data) {
            if (isBlank(dRow.getValue(0)) || isBlank(dRow.getValue(1)))
                data.remove(dRow);
        }
        foretell.setNum(data.size());
        for (DataRow dRow : data) {
            int time = getInt(dRow.getValue(0));
            double d = getDouble(dRow.getValue(1));
            foretell.setData(time, d);
        }
        if (!isBlank(willTime)) {
            foretell.setWillTime(getInt(willTime));
            return foretell.getForetellData();
        }
        return 0.0;
    }
 
    public String getExplainStr() {
        return foretell.getExplainStr();
    }
 
    public boolean isBlank(String str) {
        return str == null || "".equals(str);
    }
 
    public int getInt(String str) {
        int result = 0;
        try {
            result = Integer.parseInt(str);
            if (result < 0) {
result = 0;             MyLogger.debug("" + str + "修正为" + result);
            }
        } catch (Exception e) {
            MyLogger.debug("转换为正数失败:" + str);
        }
        return result;
    }
 
    public double getDouble(String str) {
        double result = 0.0;
        try {
            result = Double.parseDouble(str);
            if (result < 0) {
                result = 0;
                MyLogger.debug("" + str + "修正为" + result);
 
            }
        } catch (Exception e) {
            MyLogger.debug("转换为正数失败:" + str);
        }
        return result;
    }
 
    public IForeTell getForetell() {
        return foretell;
    }
 
    public void setForetell(IForeTell foretell) {
        this.foretell = foretell;
    }
 
    public List<DataRow> getData() {
        return data;
    }
 
    public void setData(List<DataRow> data) {
        this.data = data;
    }
 
}
欢迎大家讨论指正。