继承和组合

继承和组合都可以实现复用的目的,要根据现实意义来区分用哪一种,就像接口和抽象类的区别,其实这两种方式的开销是差不多的,举个列子如下(摘自《疯狂java讲义》):

  ①继承方式

package 疯狂java讲义;

public class InheritTest {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Bird bird = new Bird();
        bird.breath();
        bird.fly();
        Wolf wolf = new Wolf();
        wolf.breath();
        wolf.run();
    }

}

class Animal{ private void beat(){ System.out.println("心脏跳动"); } public void breath(){ beat(); System.out.println("呼吸……"); } } class Bird extends Animal{ public void fly(){ System.out.println("鸟会飞行……"); } } class Wolf extends Animal{ public void run(){ System.out.println("狐狸会跑……"); } }

  ②组合方式

package 疯狂java讲义;

public class CompositeTest {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Animal1 a1 = new Animal1();
        Bird2 bird = new Bird2(a1);
        Wolf2 wolf = new Wolf2(a1); bird.Breath(); bird.fly(); wolf.Breath(); wolf.run(); } } class Animal1{ private void beat(){ System.out.println("心脏跳动"); } public void breath(){ beat(); System.out.println("呼吸……"); } } class Bird2{ private Animal1 a; public Bird2(Animal1 a){ this.a = a; } public void Breath(){ this.a.breath(); } public void fly(){ System.out.println("鸟会飞行……"); } } class Wolf2{ private Animal1 a; public Wolf2(Animal1 a){ this.a = a; } public void Breath(){ this.a.breath(); } public void run(){ System.out.println("狐狸会跑……"); } }

  两种方式达到的效果是一致的。但是对于例子中的情况来说是应该用继承的方式的。因为理解应该是:鸟和狐狸是动物的一种,并非说鸟和狐狸是由动物组成的。如果一个人由手,脚,头,身体组成的,这时候就应该使用组合的方式,可以定义五个类,class 人里面是由class 手,class 脚, class 头,class 身体组合而成。继承是is-a的思想,组合是has-a的思想。

  另外,想实现以上的功能,其实也可以不用继承,也不用组合方式,如下:

package 疯狂java讲义;

public class CommonTest {

    public static void main(String[] args) {
        Animal3 a = new Animal3();
        Bird3 bird = new Bird3();
        Wolf3 wolf = new Wolf3(); bird.Breath(a); bird.fly(); wolf.Breath(a); wolf.run(); } } class Animal3{ private void beat(){ System.out.println("心脏跳动"); } public void breath(){ beat(); System.out.println("呼吸……"); } } class Bird3{ public void Breath(Animal3 a){ a.breath(); } public void fly(){ System.out.println("鸟会飞行……"); } } class Wolf3{ public void Breath(Animal3 a){ a.breath(); } public void run(){ System.out.println("狐狸会跑……"); } }

  那当这几种方法如何取舍呢?其实这就是考究一个人的面向对象的思想,要站在思想的高度去理解问题的本质。如果是继承关系的就用继承,如果是组合关系的就用组合,如果是工具类,就用第三种方法,都是看个人对问题的理解以及考虑以后的扩展去设计。有些人会说,如果这样的话,我何必还要通过传参数的方式把Animal传进来,一下这样也可以啊:

  

package 疯狂java讲义;

public class CommonTest2 {

    public static void main(String[] args) {
        Bird5 bird = new Bird5();
        Wolf4 wolf = new Wolf4();
        bird.Breath();
        bird.fly();
        wolf.Breath();
        wolf.run();

    }
}

class Animal5{ private void beat(){ System.out.println("心脏跳动"); } public void breath(){ beat(); System.out.println("呼吸……"); } } class Bird5{ public void Breath(){ Animal5 a = new Animal5(); a.breath(); } public void fly(){ System.out.println("鸟会飞行……"); } } class Wolf4{ public void Breath(){ Animal5 a = new Animal5(); a.breath(); } public void run(){ System.out.println("狐狸会跑……"); } }

  的确这样也是可以的如果Animal是一个通用类也可以说是工具类的时候,的确是可以这样的,并且这样和方式上一种方式也并没有什么区别,都不是属于继承和组合的方式,只是把Animal当做一个工具来使用,需要的时候就拿过来使用一下,完全是和面向对象无关的,和当前主业务是无关的,只是一个辅助品,就是一个手机,并非我们的必需品,你能拿手机跟我们的手相提并论么,手机要的时候我可以用一下,不需要的时候就丢掉,你自己的手你可以要就接上,不需要的时候就砍掉么?(当然,爱疯除外,很多人要爱疯不要肾……)就是因为手机是一个工具,对人来说只是一个附加品。如果手机只有一个或者要向别人借的,那就通过类外实例化传参数的方式(毕竟不能经常向别人借,这样总不好)。如果手机遍地都是,那就可以需要的时候才实例化一个手机出来用,自己慢慢理解了。既然说到了这里,那就再顺便说下,这就向是线程池或者数据库连接的连接池或者说是内存了,这些都是比较珍贵的资源或者说是对性能影响比较大的,这时候就最好是创建一个,然后能够重复利用,而每次需要的时候又重新创建一个的话,会导致开销很大,浪费很多资源。比如所Animal很大,new那么多对象出来就会很影响性能了。可能有人说,new 一个,在那个函数结束的时候,就已把Animal占用的资源释放了呀,哪有什么影响。其实虽然说作用域是结束了,但是对于像java或.net这些平台来说,作用域结束了,只是没有指针再指向堆里面的这个对象了,要等待GC回收才是真正释放了他所占的内存,所以,如果Animal很大的话,就会导致平台上的线程默认堆栈很快就到达了极限大小,然后触发GC回收,GC也是一个程序,也需要占用CPU,并且还会引起内存重组,防止出现内存碎片,所以如果是大对象或者是比较耗资源的对象就不要频繁地new一个出来,要有线程池和连接池的思想,new一个出来重复利用,这样能减少很多消耗,提高很多性能,所以告诫各位,千万别再一个循环里面new一个大对象,很容易导致宕机的,哈哈~~。但是如果像是string这些类,很小压根不占什么内存的,就可以在需要的时候就直接new一个出来就可以了。(注意:类大不大,是看类的属性多不多,并非方法;重不重要是看类对应管理的计算机资源缺不缺)

  其实这些模式都不是定死的,都是根据具体问题具体分析,不断变化不断发展不断完善的。

转载于:https://www.cnblogs.com/ismallboy/p/5378379.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值