【组合】设计思路 及 与继承和多态结合的 完美所在 文章目录概况·引出组合·概念·引入区别 —— 继承 组合Is-a Has-a 的抽象 解释耦合度再分析 设计优化层面 的区别组合优于继承类爆炸总体剖析 —— 继承·组合·多态结语概况·引出[组合]按正常来说是继承最后一个内容但我认为其完美结合是继承和多态一起因此本篇文章从继承多态出发全面剖析【组合】组合·概念·引入在【继承】博客中分析过其的优势所在到此处为止可知道弊处是 多层继承 会出现代码维护方面的问题但也可通过final来避免但一种东西总有弊处只不过弊处不明显恰如一初始化方面恰如二继承解决了static不足的地方另外继承在各种代码方面没有明显不足此时在动态拓展用户选择方面便是不足的地方也是弊处所在解决这个不足的便是“组合”组合这个概念其实在类和对象的内容章节 就有了 —— 对某个类创建对象即在一个类中创建另一个类的对象 是Java关系中的“组合” 一个类继承另一个类则是Java关系中的“继承”区别 —— 继承 组合假如有两个类在第一 个类里创建针对第二个类的对象和第一个类直接继承第二个类表面看这两种似乎在第一个类中都可以直接调用第二个类的所有成员隐藏的除外这两种方式有区别先分析最本质的区别耦合度 和 封装性组合即在第一个类里 创建第二个类的对象两个类之间是相互独立的第一个类只能通过对象与第二个类交互松 藕和人话就是只能通过对象引用 来调用第二个类的成员就是说只能通过这种方式来初始化和修改第二个类的成员数据 这样第二个类就是第一个类的组成部分假如第一个类的功能是造车那么第二个类可能是造轮胎造车的必要步骤之一就是造轮胎所以造轮胎第二个类就是造车第一个类的组成部分在第一个类中定义成员即使与第二个类的成员名字相同也不会干扰第二个类里面的细节就是这两个类成员变量名字相同值不同因为是处于不同类所以成员变量及值会储存在不同的内存空间互不干扰。即通过组合第一个类造车无需了解第二个类造轮胎的内部细节可通过调用直接使用第二个类的功能造轮胎提供给 造车的过程中使用极大程度防止破坏第二个类的封装性第二个类造轮胎的实现 并不依赖 第一个类造车换言之我自己造轮胎跟你造车又何关系所以造轮胎第二个类的细节并不透露给造车第二个类【封装性 好】我造好轮胎后你造车只管选一个轮胎品牌去用就行我造轮胎是独立于你造车而实现的 【松 耦合】继承很明显两个类确认继承关系后就相当于是同为一类子类就是在父类的基础上继续进行代码编写设计即是子类依赖父类的实现紧 耦合 就是说子类是父类的改版假设父类的结果实现是做出“普通轮胎”子类则是轮胎的不同品牌如雪地胎越野胎等。雪地胎越野胎是针对普通轮胎做出的改版即是雪地胎越野胎子类依赖普通轮胎父类 来实现紧密相连是为 紧 耦合由于两个类之间继承后几乎同为一体所以父类的细节对子类来说是公开的此时对父类来说封装性被极大破坏 就是我造雪地胎第二个类子类必须依赖你造普通轮胎第一个类父类 的基础上实现【紧 耦合】所以造普通轮胎第一个类父类的细节必须透露给造雪地胎第二个类子类即【封装性 差】总结分析区别主要在第二个类是否在第一个类的基础上 实现换个表达就是第二个类是否依赖于第一个类组合第一个类只是对第二个类功能的取用第二个类的实现基本独立于第一个类不在第一个类的基础上而实现。继承可以说第二个类子类的功能是第一个类父类功能的延续而组合中第二个类的功能与第一个类的功能是 取用关系不是延续关系Is-a Has-a 的抽象 解释书上总有“Is-a” “Has-a” 对继承和组合的描述 我只想说谁想到这种解释的抽象继承关系上子类是父类功能的延续即A_Tire子类是Tire父类的一种就是“Is-a”的关系组合在Car里面创建对Tire的对象这之间是取用关系即是Car里有Tire车有轮胎车必须有轮胎及其的功能才算车就是车对轮胎功能的取用是取用关系就是“Has-a”的关系耦合度—— - - -官方主流分析耦合度Coupling也叫耦合性是软件工程中用于衡量不同模块或类之间相互依赖程度的指标 。简单来说它描述了当你修改一个模块时对其他模块可能造成的影响有多大。耦合度越高模块间的联系就越紧密独立性就越差反之耦合度越低模块就越独立耦合 聚合耦合和内聚是相辅相成的两个概念耦合 (Coupling) 关注的是模块之间的关系。内聚 (Cohesion) 关注的是模块内部各元素之间的关联程度。一个设计良好的系统通常追求 “高内聚低耦合”。这意味着每个模块都职责单一、功能集中高内聚同时模块之间的依赖关系尽可能简单、松散低耦合再分析 设计优化层面 的区别书上大部分老师说“组合优于继承” “能用组合尽量用组合”说是组合 耦合度和封装好 还好理解其实已经好有点抽象难以理解了到最后一个理由 ——“组合”灵活性高支持动态组合为什么 喵的这是当时我根本理解不了一点抽象至极在了解这一点原因后由于理解不通忽然对“组合”“继承”变得好陌生根本不知道何时使用它们不是只有耦合度和封装性的区别吗为什么组合灵活性高难道这两种不是 在第一个类子类中都可以直接调用第二个类父类的所有成员隐藏的除外吗 只是有两种不同的实现方式其目的不都是一样 为什么有灵活性的区别冥想的那几段时间想通了这一点又被其他地方堵塞了云里雾里在一直查阅之后终于融会贯通了回头看发现理解好“灵活性动态组合”才是真正搞清了何为“组合”何为“继承”搞清后对代码来说设计层面上会很好地优化代码避免代码冗长就是跨入了“软件框架设计”的门槛如何在主类中凸显组合的优势 —— 灵活性高需多态及注入方法的完美结合这也是我当时一直想不通的点需用到多态的知识点组合优于继承”组合“和”继承“ 如何融入代码设计中即如何完美 结合 ”继承“ ”组合“ ”多态“ 如何淋漓尽致体现其 灵·活·性 灵活性 是这些内容模块在代码设计中一起结合的 精华所在可不看先讨论“组合”如何使用组合就是对 某类创建对象通过对象的实例化 把多个类 集中在一个类后续称这个类为“集中类”里面那么在主类里就可以通过这一个集中类间接调用多个类。 一般创建对象都是通过对象调用·对应类里面的成员但这样做就相当于在主类创建的对象里 调用其类里面的又一个对象相当于在主类里调用一个类第一个类却在该调用的类里再一次调用另一个类第二个类就是为了调用第二个类先调用第一个类为过渡为什么这样搞最终调的是第二个类却还要调第一个类为什么不直接调用第二个类第二个类最后可能调用的是其 子类 用的就是 向上转型 抽象吧这一段是我当时没有举例子的 解释可能很抽象可不看有例子的解释在下面假设第一个类的功能是造车定义为“Car类”第二个类的功能是造轮胎定义为“Tire类”有许多不同品牌的轮胎即为Tire的子类。造车肯定是要装轮胎的所以在Car类里对Tire类创建对象就是为了在Tire类里造好了的轮胎装到车Car类上。Car类的功能是造车的必要步骤如果要造某些品牌的车步骤大致是相同的但肯定有不同因此在造某品牌车时该某品牌车的类称为主类要继承Car类并对Car类做该品牌车的细节修改最后造成该品牌的车。不同品牌的车轮胎肯定不同因此继承了Car类的主类里如何选择轮胎即是在主类中如何通过Car类调用Tire的子类此时需要在Car类里 创建一个方法即为“注入方法”“注入方法”顾名思义就是为了注入哪个类的方法人话就是就是要装哪个轮胎通过这个方法接收publicclassCar{//做普通车的类publicvoidsetTire(Tiretire){……(把轮胎装进车里的步骤)}……除装轮胎外造车的其他步骤}publicclassTire{……造轮胎的步骤}publicclassA_TireextendsTire{……对普通轮胎的改版成为A轮胎即轮胎的品牌A}publicclassB_TireextendsTire{……对普通轮胎的改版成为B轮胎即轮胎的品牌B}publicclassA_CarextendsCar{//对普通车的改版类即是车的品牌A这个类即是为该品牌造车 就是造A车那么就要装A轮胎publicstaticvoidmain(Strings[]args){A_TireanewA_Tire;//先把A轮胎造好方便后续把A轮胎直接提供 造车步骤中 装轮胎 所需的轮胎喵的真拗口car.setTire(a);//把造好的轮胎直接当作参数传给 注入方法该方法的功能就是为车 装轮胎}}上方的演示代码多态体现在 注入方法明显可见其为 向上转型的方式之一 —— 方法传参就是传的都是轮胎需完成某个行为但传的轮胎对象不同不同的对象去完成最后车上的轮胎不同产生出不同 的状态就是多态通过在主类A_Car类里创建对Car的对象再通过该对象通过装轮胎的方法“注入方法”此时变想要装什么轮胎呢 然后针对各种轮胎需要哪种轮胎就给对应的类创建对象然后当作参数输入进注入方法然后这个车的轮胎就装成功了这段代码就是我之前总是提到的“组合·继承·多态 的完美结合”还说其最大的优势 灵活性所以其灵活性体现在哪 —— 想装哪个轮胎就装哪个类爆炸优势都是对比出来的多态的体现是在类的传输里这样设计的核心就是组合有人说不就是装轮胎吗为什么不在Car类里面提前把轮胎装好就是说一个Car类里只能装一种轮胎如果有多种轮胎就要创建多个Car1,Car2…… 会独自分析该种情况难描述这个分析可看可不看不说其他的这些个Car类里面只是轮胎不同大部分的不变不就是复制粘贴改变其中的某些选择这样只会体现代码设计不佳类之间有大部分雷同还有多个类一个专属名词描述这种场景 —— ”类爆炸“ 如果为每种车装一种轮胎而创建一个Car类这样Car类会有多少即是什么程度的”类爆炸“CarWithMichelinTire (装米其林胎的车)CarWithBridgestoneTire (装普利司通胎的车)CarWithSnowTire (装雪地胎的车)……如果你有 10 种车5 种轮胎你就得写 10 \times 5 50 个类这50个类只是某些改变代码设计极其不佳代码极其冗长这就是代码的 类爆炸因此提前装轮胎不如在造车时 实时选轮胎这样就只需一个Car类想装哪个轮胎就创建对Tire某个子类的对象(就是灵活便是在此处凸显了”灵活性“)并把他提供给Car类的注入方法就完美解决了”类爆炸“。 ”继承 组合“的方式其中包含向上转型这样设计极佳极大提高代码可读性创建一个Car类该Car类就只是是造车的流程包括如何装轮胎如何刷油漆Car类只提供”如何造“没说要装哪种轮胎刷哪种油漆就是说Car里面只是实现行为没有实现的条件轮胎没给油漆没给何时给条件 是在 实际造某品牌的车 的类里继承Car类并提供装的哪个轮胎提供条件此时轮胎才会装到车上。不是说类之间改变少就不该存在恰如Tire的子类Tire只是普通轮胎如果有多个品牌的轮胎就继承成为Tire的子类这样可以借助Tire类 极大方便 来设计不同轮胎即使有多个不同的轮胎即多个子类就是有多个改变不大的类这样的类存在有独自的意义就不是”类爆炸“总体剖析 —— 继承·组合·多态继承·组合·多态的组合型代码设计思想即是适时使用”继承“和”组合“然后在使用时加以“多态”思想 其 灵·活·性 是设计层面对代码的极大优化代码简短可选择范围大可随时而变这种设计思想灵活性得归功于多态中向上转型就是子类能向父类兼容转型。其灵活性不止体现在类之间的灵活选择性多样在类里面也会体现类里面 代码逻辑编写的灵活性这样设计后代码会更加 极简即降低圈复杂度结语以上结论带有我自己对该内容理解而总结得出可能分析不全用词不适总结不当接受批评欢迎指出