论坛首页 Java企业应用论坛

Core Java之OO继承设计技巧

浏览 8564 次
精华帖 (0) :: 良好帖 (2) :: 新手帖 (0) :: 隐藏帖 (1)
作者 正文
   发表时间:2009-11-30  
OO
OO经过这么多年的锤炼和考验证明是极好的,虽然也有些的人提出一些反面的意见,证明时代在发展、进步大家需要更先进的设计方法,不过OO终归是目前应用最为广泛也最为适用的程序设计方法学。个人觉得适用最为重要,毕竟OO是能够很好解决大多数复杂系统设计的。不过同时OO也让设计者陷入一个两难的境地。一来容易设计过轻,也就是设计的不够,发挥不了OO的强大和精妙之处,面向过程和面向对象的夹杂反而使得实现者摸不着头脑非常痛苦(很多时候这里指的设计者和实现着会是同一个人);二来容易设计过度,让OO从一个手中的工具变成了一块脚下的石头,让实现者工作起来异常的不顺利,觉得做了很多脱了裤子放屁的事情(请容许我的粗鲁,因为我再也找不到比这个更好的比喻了)。

      要解决这些问题往往需要经验的积累和技巧的总结,知道OO理论的人不少,真正在设计中运用的好的确实不多。当然OO设计中最最重要的一个部分就是继承了,下面列举一些常见的继承设计技巧,读过《Core Java》的人可能对它们非常熟悉,我结合我自己的理解做一些说明,也当作一个学习。当然不是记住了这些所谓的技巧就学会了继承设计,总的来讲设计是需要遵循一定规律、结合实际情况、发挥自己的经验而做出的,还是需要自己多多总结和积累。

1.  将公共操作和域放置在超类

      显然这是继承最基本的目的,减少编码量,减少业务关注面。让子类更多关注自己的业务实现,而公共的由共同的超类去操心。


2.  不要使用受保护的域

      很多程序员其实都很喜欢“受保护的”(protected)这种作用域,特别是应用在域上,因为在这种作用域的作用下子类可以轻松的直接访问超类中相应的域,可能也觉得这是理所当然的事情,因为既然在子类中继承了这个域而不能直接使用它还需要使用super关键字来调用超类方法去访问往往显得很别扭和难看。但是protected机制会带来很严重的安全问题,第一,因为子类集合是无限制的,任何人都可以由一个类派生出另外一个子类,并编写代码直接访问protected的实例域,从而破坏封装性;第二,在Java中同一个包中的所有类都可以访问protected域,而不管它是否为这个类的子类。

      所以推荐在尽可能的情况下把域设置为私有,不允许外部直接访问甚至修改。但其实很多初学者,包括一些编程老手都没办法理解和接受这种做法。我个人认为如果OO失去了封装性就好比失去了灵魂的空壳,没有了什么意义,反而变成累赘而已。


3.  使用继承实现is-a关系

      如果抛开所谓的设计思想来看,实现继承最基本的目的就是节省代码量,并且很容易就做到。但这样往往很多人会滥用继承,纯粹为了节约代码而节约代码,而没有顾及超类与子类的关系导致在实现其他相关问题的时候带来很多麻烦,反而会多写很多代码,捡了芝麻丢了西瓜。

      继承应该要遵循is-a关系,要判断是否遵循了is-a关系也有个很简单的办法,就是你念出这么一句话:“子类”是个“超类”,看是否合理。例如有一个雇员(Employee)类继承与人(Person),这个时候就有这样的关系:雇员是个人,显然是正确的。


4.  除非所有继承的方法都有意义,否则不要继承

      当子类和超类之间遵循了is-a关系,但子类从超类继承来的某些方法对于子类是没有意义的,甚至是实现错误功能的,这个时候应该取消继承关系,因为这相当的危险。或者可以选择重新审视你的设计。


5.  在覆盖方法的时候,不要改变预期的行为

      结合上面4中的观点,有些人可能会说这个很简单,把意义不同的方法在子类中重写,或者干脆什么也不做,也或者抛出一个异常不久解决了,so easy!其实这样也是违背OO思想的,应该尽量保持覆盖方法的预期行为,只可能因为各自的业务含义而改变实现方式,但是语义和行为是要保证的,就好像超类有个方法名字叫add是用来做加法的,但是你一定要极端的在子类中重写了它,里面的代码偷偷实现了一个减法,这种做法的危险我想很容易理解。为什么说是偷偷的,因为可能只有你知道这里是做了减法,或者说几个星期后你自己都认为这个方法实现的是一个加法运算!


6.  使用多态,而非类型信息

      很多时候需要判断当前对象的类型来执行相应不同的方法,看下面的示例代码:

1 if(x is of type 1)
2   action1(x);
3 else if(x is of type 2)
4   action2(x);
      这个时候应该去考虑action1和action2是不是表示同一个概念,如果是就应该使用多态性来处理。这个时候应该定义一个方法放置在这两个类的超类或者接口中,然后就可以调用

1 x.action();
      让语言提供的多态性自己去找应该调用那个类的方法来实现。是不是像极了某种模式:)


7.  不要过多的使用反射

      个人觉得Java拥有了反射机制简直就是太强大了,在运行时能够查看甚至修改、调用域和方法极大的提高了程序实现的灵活性和技巧性。以至于我甚至有一段时间把Java当作JavaScript来玩(爱死JavaScript的灵活性但同样具有那么优秀的OO)。看看现在大多数流行不流行的开发框架都是基于Java这种强大的能力来实现的,它让大家可以编写更加通用的程序,也是为什么它在系统程序(包括一些框架、工具甚至服务器等)中使用这么广泛并都作为核心技术;但是在编写应用程序的过程中应该减少反射的使用,因为反射其实是很脆弱的,编译器很难帮助大家发现程序中的错误,任何错误都到了运行时才被发现,并导致一些莫名其妙的异常。说起莫名其妙其实不是说反射功能不够健壮或有问题,而是出现错误后很难跟踪和排查,给开发和维护带来很大困难。

      还有一点也很重要,反射比直接调用慢,这个要时刻记住。所以应该用接口来实现回调之类的功能而不是反射。




      其实这些只是继承技巧的冰山一角而已,每个人在设计过程中都会总结出自己的经验。

      总的来说我们应该用理论来指导实践,而在实践中总结出理论!
   发表时间:2009-11-30  
<<代码大全2>>中的关于类质量的观点也值得推荐:
硬性规定:
1.类层次不宜超过三层.
2.类成员数量不宜超过7个,如果全是简单数据类型最多9个,有其它类的话限制为5个,否则需要分解成更小的类.
3.避免创建万能类
4.消除不必要的成员.
5.消除无关精要的类.
6.避免用动词命名类.

抽象:
1.类是否有一个中心目的.
2.类的命名是否表现了其中心目的.
3.类的接口是否展现了一致的抽象.
4.类的接口是否让人明白了知道该如何使用它.
5.类的接口是否足够抽象,使使用者不必顾虑它是如何进行服务的.
6.类提供的服务是否足够完整,能让其它类无须动用其内部数据.
7.是否已经尽量分解.
8.在修改类是是否维持了接口的完整性.

封装:
1.是否把类成员的可访问性降至最小.
2.是否避免暴露类中的数据成员.
3.类是否已经尽可能的对其它类隐藏了实现细节.
4.类是否不依赖其它类,它是松耦合的吗?
0 请登录后投票
   发表时间:2009-11-30   最后修改:2009-11-30
哎...在大学的时候这些规矩都烂熟于心,工作之后却早已“被”忘记。希望有人能坚持这些代码编写原则,为后来的程序员多积点德...
0 请登录后投票
   发表时间:2009-11-30  
事实上有些类设计的,本来应该暴露的接口设计成protect
导致必须用子类继承才能用

这才是比较郁闷的
0 请登录后投票
   发表时间:2009-11-30  
坚持规范开发!!!!!!
0 请登录后投票
   发表时间:2009-11-30  
jenchxin 写道
<<代码大全2>>中的关于类质量的观点也值得推荐:
硬性规定:
1.类层次不宜超过三层.
2.类成员数量不宜超过7个,如果全是简单数据类型最多9个,有其它类的话限制为5个,否则需要分解成更小的类.
3.避免创建万能类
4.消除不必要的成员.
5.消除无关精要的类.
6.避免用动词命名类.

抽象:
1.类是否有一个中心目的.
2.类的命名是否表现了其中心目的.
3.类的接口是否展现了一致的抽象.
4.类的接口是否让人明白了知道该如何使用它.
5.类的接口是否足够抽象,使使用者不必顾虑它是如何进行服务的.
6.类提供的服务是否足够完整,能让其它类无须动用其内部数据.
7.是否已经尽量分解.
8.在修改类是是否维持了接口的完整性.

封装:
1.是否把类成员的可访问性降至最小.
2.是否避免暴露类中的数据成员.
3.类是否已经尽可能的对其它类隐藏了实现细节.
4.类是否不依赖其它类,它是松耦合的吗?

这本大枕头,佩服你能坚持地读它,我实在啃不动,读它真的很枯燥
0 请登录后投票
   发表时间:2009-11-30  
我在一家公司写的一个项目的代码,因为一些客观因素导致编码没有任何的分层,技术负责人直接说,所有能写成JSP的都不要写成Java类,这一条直接宣布分层OVER,我在JSP中用标准标签负责人不让用,能写成代码块的干嘛要写成这东西,EL表达式他问我这是什么东西...
在彷徨了一个月后,离开了!
当我学习的时候我从来都没有写过这样的代码,在工作中确要写着我都感觉很恶心的代码.

0 请登录后投票
   发表时间:2009-12-01  
H_eaven 写道
我在一家公司写的一个项目的代码,因为一些客观因素导致编码没有任何的分层,技术负责人直接说,所有能写成JSP的都不要写成Java类,这一条直接宣布分层OVER,我在JSP中用标准标签负责人不让用,能写成代码块的干嘛要写成这东西,EL表达式他问我这是什么东西...
在彷徨了一个月后,离开了!
当我学习的时候我从来都没有写过这样的代码,在工作中确要写着我都感觉很恶心的代码.

深有同感,我每天晚上都学习到12点左右,学习core java,effective java,巩固基本功,并且学习优秀的设计思想。可是每天上班都在写着很恶心的代码,没办法,公司的人写代码就是这个风格。各种复杂的业务不加思索拿来就做,两个小时编码,debug两天,越改越乱。正在思考这份工作对我的意义和价值何在?
0 请登录后投票
   发表时间:2009-12-01  
chenzhou0418 写道
坚持规范开发!!!!!!

昂 规范很重要
0 请登录后投票
   发表时间:2009-12-01  
zhengyutong 写道
H_eaven 写道
我在一家公司写的一个项目的代码,因为一些客观因素导致编码没有任何的分层,技术负责人直接说,所有能写成JSP的都不要写成Java类,这一条直接宣布分层OVER,我在JSP中用标准标签负责人不让用,能写成代码块的干嘛要写成这东西,EL表达式他问我这是什么东西...
在彷徨了一个月后,离开了!
当我学习的时候我从来都没有写过这样的代码,在工作中确要写着我都感觉很恶心的代码.

深有同感,我每天晚上都学习到12点左右,学习core java,effective java,巩固基本功,并且学习优秀的设计思想。可是每天上班都在写着很恶心的代码,没办法,公司的人写代码就是这个风格。各种复杂的业务不加思索拿来就做,两个小时编码,debug两天,越改越乱。正在思考这份工作对我的意义和价值何在?



这种现实和理想的差距在大多数公司普遍存在, 学习要坚持, 工作还得继续,因为生活!
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics