• 设计模式(05)——组合和继承


    组合和继承

    继承带来的问题

    《面向对象以及特性分析》文章,我们可以看到继承带来的问题:

    1. 菱形问题;
    2. 继承层次过深过复杂。


    image.png

    如上图所示,因为每个鸟根据特性会有会飞或者不会飞的特性,也会有会叫不会叫的特性等等,如果根据这些特性来设计类,然后让对应的终点类来继承的话,那么则会造成类的膨胀,从而代码变得十分的复杂。

    组合的优势

    针对上述继承所带来的问题,我们可以通过组合、委托、接口 3个技术手段,来进行另一种层面上的实现,具体代码如下。

    // ================================  接口定义 ==============================================
    public interface Flyable{
    	void fly();
    }
    
    public interface Tweetable{
    	void tweet();
    }
    
    public interface EggLayable{
    	void layEgg();
    }
    
    // ================================   委托类(通过在委托类中定义具体的代码实现,从而使用 组合 的形式来消除重复代码,做到复用)  ==============================================
    public class FlyAbility implements Flyable{
    	@Override
        public void fly(){
        	// 具体实现
        }
    }
    
    public class TweetAbility implements Tweetable{
    	@Override
        public void tweet(){
        	// 具体实现
        }
    }
    
    public class EggLayAbility implements EggLayable{
    	@Override
        public void layEgg(){
        	// 具体实现
        }
    }
    
    // ==============================  具体类   ================================================
    public class Ostrich implements Tweetable,EggLayable{
        // 组合上层实现
        private TweetAbility tweetAbility = new TweetAbility();
        private EggLayAbility eggLayAbility = new EggLayAbility();
        
        // 通过组合,就不需要编写重复代码
        @Override
        public void tweet(){.
            tweetAbility.tweet();
        }
        
        @Override
        public void layEgg(){
        	eggLayAbility.layEgg();
        }
    }
    
    public class Sparrow implements Flyable,Tweetable,EggLayable{
        private FlyAbility flyAbility = new FlyAbility();
        private TweetAbility tweetAbility = new TweetAbility();
        private EggLayAbility eggLayAbility = new EggLayAbility();
        
        @Override
        public void fly(){.
            flyAbility.fly();
        }
        
        @Override
        public void tweet(){.
            tweetAbility.tweet();
        }
        
        @Override
        public void layEgg(){
        	eggLayAbility.layEgg();
        }
    }
    

    使用时机

    根据上面的分析,可能觉得既然继承有那么多的问题,那干脆就不要用了吧,全都用组合多好。

    其实不是这样的,继承和组合都各自有其代表的语义。

    • 继承代表的是 is-A 关系,代表子类是父类的一种特殊情况;
    • 组合代表的是 has-A 关系,代表的是被组合的类是父类的一部分;

    此外继承还用简单易理解的方式,实现了代码的复用,因此如果逻辑比较简单,还是可以使用继承的。具体使用方式就需要开发人员根据具体情况具体分析了。

    公众号截图




    文章在公众号「iceWang」第一手更新,有兴趣的朋友可以关注公众号,第一时间看到笔者分享的各项知识点,谢谢!笔芯!

  • 相关阅读:
    Oracle数据库系统结构二(实例结构)
    Oracle数据库系统结构一(存储结构)
    SQL Plus的使用详解(登录和常用命令)
    Oracle的基本了解和配置
    Oracle11g的安装及删除
    C++编译预处理
    C++程序的多文件组织
    C++变量的存储类型
    C++动态存储方式与静态存储方式
    C++函数五(局部变量与全局变量和域运算符)
  • 原文地址:https://www.cnblogs.com/JRookie/p/13958742.html
Copyright © 2020-2023  润新知