首页 > 其他分享 >设计原则之组合优先继承

设计原则之组合优先继承

时间:2023-06-11 15:33:21浏览次数:28  
标签:Engine engine 优先 set 组合 get 继承 car public

“组合优于继承”是一个面向对象编程的设计原则,它建议我们在需要复用代码的时候,尽量使用组合(has-a)的方式,而不是继承(is-a)的方式。组合是指一个类包含另一个类的对象作为自己的属性,而继承是指一个类直接从另一个类派生出来,拥有其所有的属性和方法。

为什么要使用组合而不是继承呢?主要有以下几个原因:

  • 组合可以提高类的封装性灵活性。通过组合,一个类可以动态地改变自己的行为,只需要改变包含的对象的引用即可。而继承则是静态的,一旦确定了父类和子类的关系,就无法在运行时改变。而且,通过组合,一个类可以复用多个类的代码,而继承则只能单根继承,不能同时从多个父类派生。
  • 组合可以避免类之间的耦合污染。通过继承,子类会暴露父类的内部实现细节,如果父类发生了变化,子类也必须跟着改变。而且,子类会无条件地继承父类所有的属性和方法,即使有些并不适用于子类。这样会造成子类的臃肿和混乱。通过组合,一个类只需要关心自己包含的对象提供了哪些接口,而不需要知道其内部实现。而且,一个类可以选择性地使用包含对象的属性和方法,不会被强制继承不需要的东西。

下面我给你举一个简单的例子来说明组合和继承的区别。假设我们要设计一个汽车(Car)类和一个发动机(Engine)类。如果我们使用继承的方式,那么我们可以让汽车类继承发动机类,这样汽车就拥有了发动机的属性和方法。但是这样做有几个问题:

  • 首先,这样违反了“is-a”的逻辑关系。汽车并不是一种发动机,它们之间没有本质上的层次结构。
  • 其次,这样导致了汽车和发动机之间的紧密耦合。如果发动机类发生了变化,比如增加了一个新的属性或方法,那么汽车类也必须跟着改变。这样会增加代码的复杂度和维护成本。
  • 再次,这样限制了汽车和发动机之间的灵活性。如果我们想让汽车换一个不同类型或品牌的发动机,那么我们就必须重新定义一个新的汽车子类来继承那个发动机类。这样会导致代码冗余和浪费。

使用C#语言来表示就是这样:

// 使用继承的方式
public class Engine
{
    public string Type { get; set; }
    public int HorsePower { get; set; }

    public void Start()
    {
        // Start the engine
    }

    public void Stop()
    {
        // Stop the engine
    }
}

public class Car : Engine // Car is not an engine!
{
    public string Model { get; set; }
    public string Color { get; set; }

    public void Drive()
    {
        // Drive the car
    }
}

// 如果想换一个不同的发动机,就要定义一个新的子类
public class CarWithElectricEngine : ElectricEngine // Car is not an electric engine!
{
    public string Model { get; set; }
    public string Color { get; set; }

    public void Drive()
    {
        // Drive the car
    }
}

如果我们使用组合的方式,那么我们可以让汽车类包含一个发动机类的对象作为自己的属性,这样汽车就可以使用发动机的属性和方法。这样做有几个好处:

  • 首先,这样符合了“has-a”的逻辑关系。汽车有一个发动机,它们之间是一种组合关系。
  • 其次,这样降低了汽车和发动机之间的耦合。如果发动机类发生了变化,那么汽车类不需要跟着改变。只要发动机类提供了相同的接口,汽车类就可以正常工作。
  • 再次,这样提高了汽车和发动机之间的灵活性。如果我们想让汽车换一个不同类型或品牌的发动机,那么我们只需要改变汽车类中包含的发动机对象的引用即可。这样可以实现运行时的动态变化。

使用C#语言来表示就是这样:

// 使用组合的方式
public class Engine
{
    public string Type { get; set; }
    public int HorsePower { get; set; }

    public void Start()
    {
        // Start the engine
    }

    public void Stop()
    {
        // Stop the engine
    }
}

public class Car
{
    public string Model { get; set; }
    public string Color { get; set; }
    public Engine Engine { get; set; } // Car has an engine

    public void Drive()
    {
        // Drive the car
        Engine.Start(); // Use the engine's method
    }
}

// 如果想换一个不同的发动机,只要改变引用即可
public class Example
{
    public static void Main()
    {
        Car car = new Car();
        car.Model = "Toyota";
        car.Color = "Red";
        car.Engine = new Engine(); // Use a normal engine
        car.Engine.Type = "Gasoline";
        car.Engine.HorsePower = 200;

        car.Drive(); // Drive the car with a normal engine

        car.Engine = new ElectricEngine(); // Use an electric engine
        car.Engine.Type = "Electric";
        car.Engine.HorsePower = 150;

        car.Drive(); // Drive the car with an electric engine
    }
}

标签:Engine,engine,优先,set,组合,get,继承,car,public
From: https://www.cnblogs.com/netlog/p/17472987.html

相关文章

  • STL之优先级队列(堆)的模拟实现与仿函数(8千字长文详解!)
    STL之优先级队列(堆)的模拟实现与仿函数优先级队列的概念优先队列是一种==容器适配器==,根据严格的弱排序标准,==它的第一个元素总是它所包含的元素中最大的==。本质就是一个堆!此上下文类似于堆,在堆中可以随时插入元素,并且只能检索最大堆元素(优先队列中位于顶部的元素)。......
  • 第10章 组合模式(Composite Pattern)
    组合模式(CompositePattern)——.NET设计模式系列之十一Terrylee,2006年3月概述组合模式有时候又叫做部分-整体模式,它使我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以向处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。意图将对象组合......
  • k 倍区间(同余定理,组合数)
    题目描述给定一个长度为 N 的数列,1,2,⋯A1​,A2​,⋯AN​,如果其中一段连续的子序列 ,+1,⋯(≤)Ai​,Ai+1​,⋯Aj​(i≤j) 之和是 K 的倍数,我们就称这个区间 [,][i,j] 是 K 倍区间。你能求出数列中总共有多少个 K 倍区间吗?输入格式第一行包含两个整数 N 和 K......
  • CSS组合器(Combinators)
    前言组合器就是将选择器按照一定的语法规则进行组合,提供更丰富的元素选择方案。选择器主要分为类型选择器属性选择器类选择器ID选择器通配选择器组合器类型选择器列表(Selectorlist)如果你希望多个元素共享同一样式,可以使用该组合器,其有点类似并操作(or)。语法和示例......
  • CSS_三大特性下_优先级
    CSS三大特性1、继承性CSS_特性继承和层叠-Bublly-博客园(cnblogs.com)2、层叠性CSS_特性继承和层叠-Bublly-博客园(cnblogs.com)3、优先级3.1基本1特性:不同选择器具有不同的优先级,优先级高的选择器样式会覆盖优先级低选择器样式2优先级公式:继承<通配符选择器<......
  • CSS_特性继承和层叠
    CSS特性1、继承性特性:1、子元素有默认继承父元素样式的特点(子承父业)2、可以继承的常见属性(文字控制属性都可以继承)1.color2.font-style、font-weight、font-size、font-family3.text-indent,text-align4.line-height注意点:可以通过调试工具判断样式是否可以继承2、层叠......
  • Python内置函数any()、map()组合运用案例一则
    Python内置函数any()用来测试某个可迭代对象中是否所有对象都等价于True,map()用来把一个函数映射到一个或多个可迭代对象上。问题描述:测试一个字符串中是否包含指定列表中的某个字符串作为子串,不允许使用循环结构。参考代码:......
  • js 实现排列组合
    组合:(不考虑顺序,无重复)//测试用例letdataArr=[1,2,3,4,5];functioncombination(dataArr,remainNum,currentArr){if(remainNum===0){console.log(...currentArr);return;}for(leti=0;i<dataArr.length+1-remainNum;i++){......
  • Python组合列表中多个整数得到最小整数(一个算法的巧妙实现)
    '''程序功能:  给定一个含有多个整数的列表,将这些整数任意组合和连接,  返回能得到的最小值。  代码思路:  将这些整数变为相同长度(按最大的进行统一),短的右侧使用个位数补齐  然后将这些新的数字升序排列,将低位补齐的数字删掉,  把剩下的数字连接起来,即可得到满足要......
  • 一个根据字母,数字和符号组合生成指定长度密码的简单方法
    前言:网上没有太好的直接可用的方法,于是自己写了一个,下面的方法可以根据字母,数字和符号组合生成指定长度密码,策略和长度可控,详细代码如下: ///<summary>///生成密码///</summary>///<paramname="zmLength">小写字母长度</param>///<paramname="upzmLength">大写......