`
jendgh
  • 浏览: 16096 次
  • 性别: Icon_minigender_2
  • 来自: 济南
文章分类
社区版块
存档分类
最新评论

研磨设计模式 之 备忘录模式(Memento)1——跟着cc学设计系列

阅读更多

19.1  场景问题

19.1.1  开发仿真系统

考虑这样一个仿真应用,功能是:模拟运行针对某个具体问题的多个解决方案,记录运行过程的各种数据,在模拟运行完成过后,好对这多个解决方案进行比较和评价,从而选定最优的解决方案。

这种仿真系统,在很多领域都有应用,比如:工作流系统,对同一问题制定多个流程,然后通过仿真运行,最后来确定最优的流程做为解决方案;在工业设计和制造领域,仿真系统的应用就更广泛了。

由于都是解决同一个具体的问题,这多个解决方案并不是完全不一样的,假定它们的前半部分运行是完全一样的,只是在后半部分采用了不同的解决方案,后半部分需要使用前半部分运行所产生的数据。

由于要模拟运行多个解决方案,而且最后要根据运行结果来进行评价,这就意味着每个方案的后半部分的初始数据应该是一样,也就是说在运行每个方案后半部分之前,要保证数据都是由前半部分运行所产生的数据,当然,咱们这里并不具体的去深入到底有哪些解决方案,也不去深入到底有哪些状态数据,这里只是示意一下。

那么,这样的系统该如何实现呢?尤其是每个方案运行需要的初始数据应该一样,要如何来保证呢?

19.1.2  不用模式的解决方案

       要保证初始数据的一致,实现思路也很简单:

  • 首先模拟运行流程第一个阶段,得到后阶段各个方案运行需要的数据,并把数据保存下来,以备后用
  • 每次在模拟运行某一个方案之前,用保存的数据去重新设置模拟运行流程的对象,这样运行后面不同的方案时,对于这些方案,初始数据就是一样的了

根据上面的思路,来写出仿真运行的示意代码,示例代码如下:

/**

 * 模拟运行流程A,只是一个示意,代指某个具体流程

 */

public class FlowAMock {

    /**

     * 流程名称,不需要外部存储的状态数据

     */

    private String flowName;

    /**

     * 示意,代指某个中间结果,需要外部存储的状态数据

     */

    private int tempResult;

    /**

     * 示意,代指某个中间结果,需要外部存储的状态数据

     */

    private String tempState;

    /**

     * 构造方法,传入流程名称

     * @param flowName 流程名称

     */

    public FlowAMock(String flowName){

       this.flowName = flowName;

    }

   

    public String getTempState() {

       return tempState;

    }

    public void setTempState(String tempState) {

       this.tempState = tempState;

    }

    public int getTempResult() {

       return tempResult;

    }

    public void setTempResult(int tempResult) {

       this.tempResult = tempResult;

    }

   

    /**

     * 示意,运行流程的第一个阶段

     */

    public void runPhaseOne(){

       //在这个阶段,可能产生了中间结果,示意一下

       tempResult = 3;

       tempState = "PhaseOne";

    }

    /**

     * 示意,按照方案一来运行流程后半部分

     */

    public void schema1(){

       //示意,需要使用第一个阶段产生的数据

       this.tempState += ",Schema1";

       System.out.println(this.tempState

+ " : now run "+tempResult);

       this.tempResult += 11;

    }

    /**

     * 示意,按照方案二来运行流程后半部分

     */

    public void schema2(){

       //示意,需要使用第一个阶段产生的数据

       this.tempState += ",Schema2";

       System.out.println(this.tempState

+ " : now run "+tempResult);

       this.tempResult += 22;

    }  

}

(2)看看如何使用这个模拟流程的对象,写个客户端来测试一下。示例代码如下:

public class Client {

    public static void main(String[] args) {

       // 创建模拟运行流程的对象

       FlowAMock mock = new FlowAMock("TestFlow");

       //运行流程的第一个阶段

       mock.runPhaseOne();

       //得到第一个阶段运行所产生的数据,后面要用

       int tempResult = mock.getTempResult();

       String tempState = mock.getTempState();

      

       //按照方案一来运行流程后半部分

       mock.schema1();

      

       //把第一个阶段运行所产生的数据重新设置回去

       mock.setTempResult(tempResult);

       mock.setTempState(tempState);

      

       //按照方案二来运行流程后半部分

       mock.schema2();

    }

}

运行结果如下:

PhaseOne,Schema1 : now run 3

PhaseOne,Schema2 : now run 3

       仔细看,上面结果中框住的部分,是一样的值,这说明运行时,它们的初始数据是一样的,基本满足了功能要求。

19.1.3  有何问题

看起来实现很简单,是吧,想一想有没有什么问题呢?

上面的实现有一个不太好的地方,那就是数据是一个一个零散着在外部存放的,如果需要外部存放的数据多了,会显得很杂乱。这个好解决,只需要定义一个数据对象来封装这些需要外部存放的数据就可以了,上面那样做是故意的,好提醒大家这个问题。这个就不去示例了。

还有一个严重的问题,那就是:为了把运行期间的数据放到外部存储起来,模拟流程的对象被迫把内部数据结构开放出来,这暴露了对象的实现细节,而且也破坏了对象的封装性。本来这些数据只是模拟流程的对象内部数据,应该是不对外的。

那么究竟如何实现这样的功能会比较好呢?


---------------------------------------------------------------------------

私塾在线学习网原创内容  跟着cc学设计系列 之 研磨设计模式

 

原创内容,转载请注明出处【http://sishuok.com/forum/blogPost/list/0/5632.html

---------------------------------------------------------------------------

0
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics