程序员的自我修养
Home » Java语言, 设计模式 » 一个简单的OO问题

一个简单的OO问题

0条评论1,711次浏览

问题

一个同事发来的题目:学校有三种人员,第一种为教师,属性包括名字、教工号、电话、地址;第二种为学生,属性包括名字、学号、电话、地址、平均成绩;第三种为辅工,属性包括名字、辅工号、电话、地址、工种。使用你学到的面向对象设计的方法,实现这三种人员的类表示,并实现三种人员的添加、修改、删除,可在内存进行增删改的操作,不需要永久保存。

注,可使用List保存人员,如没有使用OO设计方法,本期作业不通过,仅使用类不是OO设计。

答案v1

大致扫了一眼题目,是一个简单的OO设计问题。于是第一版答案很快出来了。

抽象父类Staff

子类Student,Teacher和Worker类类似,在此省去。静态set用于在内存中保存对象,为了防止出现new Student().getSet()这样丧心病狂的方法来获取整个数据集,添加了静态方法list(),这样可以通过Student.list()方法来获取整个数据集。

测试

运行结果

一切都正确的,可以CRUD。但是,为何看起来那么的别扭。没有满足OO设计吗?貌似很符合,好像还采用了模版方法的设计模式。那问题出在哪里?

看看测试代码中的这两句:

对象可以调用自己的方法来操作自己的CRUD,这是一个不太常见的设计方法。反正我没在哪里看到过其它人这么设计,我第一次这么设计是以前有个系统需要大量的在工作流中添加监听器,而监听器要进行CRUD操作的时候还要从SpringContext中获取相应的Service,显得十分繁琐。于是可以自己操作自己的CURD的类就这样设计出来了。但是,这样的类在某些特殊情况下确实好用,但对于传统的思维方式来说显得就十分的异类了。就好像上面的代码,一会自己操作自己的add()方法,一会又通过静态方法Student.list()来获取数据集,相近的功能分布在了两个不同的地方。我想这就是为何觉得别扭的原因。于是传统的Service、Dao操作CRUD方法的答案就出来了。

答案v2

接口IDao,这里多添加了几个方法,使得更像一个Dao了。

实现类Dao

抽象父类Staff,现在的Staff显得十分的简洁,功能也十分的单一。

子类Student,也变得简洁了些。

测试

运行结果

这样就感觉正常多了,通过Dao来操作每个子类的CRUD,功能解耦,而且还方便扩展,例如继续添加Staff的子类,如:校(qin)长(shou),除了添加子类以外不用做任何其它的改动。

继续改进

看到那该死的5个参数的构造函数了吗?为何该死?就是太长了,5个参数,每个参数什么意义一点也不明确。若构造时只需要id和name就可以构造的话就需要重新添加一个构造函数,只需要id、name和mobile也可以构造则又需要添加一个构造函数......抓狂吧?颤抖吧?怎么解决呢?建造者模式

继续以Student为例,现假设id和name为必须的属性,其它的属性可以设置也可以不设置。采用建造者模式后的代码如下。

这样创建Student对象时则可以显示的设置每个参数,如下。

和5个构造参数的构造函数比起来是不是有种高下立判的感觉。正如Effective Java中所说的,如果类的构造器或者静态工厂中具有多个参数,设计这种类时,Builder模式就是不错的选择。当然建造者模式相对Setter、Getter方式的类各有利弊,比如上述代码中就无法改变已创建好的Student对象的属性。

最后

不同的环境下,不同的设计方式有不同的效果,能选择最适合当前环境的即可。不必要纠结于其它的条条框框。比如那个自行CRUD的设计,怎么看都是个异类,但在项目里确实是最合适的。当然,需要这样的设计来弥补的项目我不想遇到第二次(该项目持续开发了8年,经过无数人的交接,技术大部分是8年前的技术,没错,还是国企自主研发项目,你懂的。。)。

(转载本站文章请注明作者和出处 程序员的自我修养 – SelfUp.cn ,请勿用于任何商业用途)
标签:, ,
发表评论


profile
  • 文章总数:79篇
  • 评论总数:331条
  • 分类总数:31个
  • 标签总数:44个
  • 运行时间:1072天

大家好,欢迎来到selfup.cn。

这不是一个只谈技术的博客,这里记录我成长的点点滴滴,coding、riding and everthing!

最新评论
  • 增达网: 受教了!呵呵!
  • Anonymous: :!: :smile: :oops: :grin: :eek: :shock:
  • 27: :razz: dsa会报错,rsa不会
  • Anonymous: 看错了 忽略我
  • Anonymous: UserSideCF这个类在哪里
  • 晴子: 在主节点初始化CM5数据库的时候报错误:Verifying that we can write to /opt/cm-5.9.0/etc/cloudera-scm -server log4j:ERROR Could not...
  • zhangnew: 就4题 :?:
  • linxh: “ 但要是遇到预先并不知道数组的长度而又需要获取正确的(或者称之 为原始的)split长度时,该如何处理呢。。? ” 印象中可以split函数参数传-1?
  • linxh: 班门弄斧一下: ssh host cmd 和直接ssh上后cmd结果不一样是因为ssh直接运行远程命令 是非交互非登录模式与ssh上去得到一个登录交互式Shell二 者加载的环境变量不一样。
  • 匿名: 其实文本分类和数字分类是一样的,只是文本分类需要多一个步骤, 就是计算它的tf-idf值将其转换为double类型
  • yurnom: 可能苹果最近又改变了返回值吧,最近没做测试了。 BadDeviceToken一般测试环境和正式环境弄错的情况 下会出现。
  • Anonymous: :razz: 博主,良心贴啊, 最近也在弄apns推送。 有个问题想请教你一下啊。 你博客中写的 Unregistered 错误,有准确的说明吗, 我看你博客中写的:...
  • 一波清泉: 回复邮箱: 1004161699@qq.com 多谢
  • Anonymous: 17/02/09 01:15:02 WARN Utils: Service ‘SparkUI’ could not bind on port 4040. Attempting port...
  • pacificLee: :twisted:
  • 小码: 为什么没有后面的呢,只有前10个
  • Anonymous: :lol:
  • Anonymous: :razz: 楼主是属于会聊天的。 我想问,sqoop发了几个版本了,应该没这些问题了吧。
  • Anonymous: Config.kafkaConfig.kafkaGroupI d 这个是指自己配置的group id 还是从 import org.apache.kafka.common.config .Config 这个类...
  • Anonymous: ZkUtils.getPartitionsForTopics (zkClient, Config.kafkaConfig.topic) 那个方法是在 spark-streaming_2.10 中 kafka...