原型模式介绍
原型模式主要解决的是创建重复对象的问题,而这部分对象内容本身比较复杂,从数据库或者RPC框架获取相关对象数据的耗时较长,因此需要采用复制的方式节省时间。
原型模式简单使用
每个人都经历过考试,大部分情况都是在纸质的试卷上答题,随着互联网的兴起,也有一些考试改为上机考试。从时间效率和成本上看,上机考试可以大大降低哦按卷的人工成本,提高判分效率。上机考试还可以提高考试的公平性,将同样的题目混排,可以更好地降低抄袭的可能性,在这种情况下对应的答案也是混排。同样的试卷题目,如果是人工判卷,很难实现题目混排,但放在计算机上,无论是生成试卷还是判卷都能轻而易举的实现。
下面来实现这样的功能:同一张试卷、同样的题目、同样的答案,把题目和答案全部混排。
模拟场景
在模拟的场景:有选择题,解答题
选择题
1 | package com.bestrookie.design; |
解答题
1 | package com.bestrookie.design; |
违背设计模式实现
首相想到就是一坨一坨的代码
1 | package com.bestrookie.design; |
以上代码主要包括三部分:将选择题和问答题创建到集合中,定义详情字符串包装结果,返回结果内容。但从代码阅读上来说,这样的代码并不复杂,且更易于理解。因为就这段代码来说不是面向对象,而是面想过程,业务逻辑需要什么就直接写什么。不考虑扩展性,能跑就完事了。但是这段代码没有实现题目和答案乱序的功能,最终所有人的试卷都是一样的。如果需要增加混排题目功能,则代码时间就会非常混乱。
原型模式实现
原型主要解决的问题是创建大量的重复对象,而这里模拟的场景同样是需要给不同的考生创建相同的试卷,但在创建过程中,这些试卷的题目不应该每次都从数据库或者远程RPC接口中获取。这些操作都是非常耗时的,而且随着创建对象的增多,将严重降低创建效率。
- ChoiceQuestion、AnswerQuestion被用在题库创建中;
- Topic 是选项和正确答案组成的类
- TopicRandomUtil 是将选项乱序
- 核心题库类QuestionBank主要负责将各个题目进行组装,最终输出试卷
Topic
1 | package com.bestrookie.util; |
TopicRandomUtil
1 | package com.bestrookie.util; |
QuestionBank
1 | package com.bestrookie; |
这个类中的操作内容主要包括一下三个方面
- 两个append()对各项目的添加有点像在建造者模式中使用的方式-—添加装修材料
- clone()的核心是复制对象,这里的复制不仅包括对象本身,也包括两个集合。只有这样的复制才能确保在操作复制对象时不影响原对象
- 混排操作在list集合中有一个方法——Collections.shuffle,可以将原有集合的顺序打乱,输出一个新的顺序
InitQuestionBank
1 | package com.bestrookie; |
总结
- 以上的实际场景模拟了原型模式在开发中重构的作用,但是原型模式的使用频率确实不是很高。如果有一些特殊场景需要使用到,也可以按照此设计模式进行优化。
- 另外原型设计模式的优点包括;便于通过克隆方式创建复杂对象、也可以避免重复做初始化操作、不需要与类中所属的其他类耦合等。但也有一些缺点如果对象中包括了循环引用的克隆,以及类中深度使用对象的克隆,都会使此模式变得异常麻烦。
- 终究设计模式是一整套的思想,在不同的场景合理的运用可以提升整体的架构的质量。永远不要想着去硬凑设计模式,否则将会引起过渡设计,以及在承接业务反复变化的需求时造成浪费的开发和维护成本。
- 初期是代码的优化,中期是设计模式的使用,后期是把控全局服务的搭建。不断的加强自己对全局能力的把控,也加深自己对细节的处理。可上可下才是一个程序员最佳处理方式,选取做合适的才是最好的选择。