百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

C#之面向对象编程五大原则(c#面向对象的编程)

liebian365 2024-11-17 13:18 20 浏览 0 评论

  • 单一职责原则
  • 开闭原则
  • 里氏转换原则
  • 接口隔离原则
  • 依赖倒转原则

单一职责原则

简单点理解,类型应当只具有一种功能,功能要单一,例如操作数据库的类则不应该再有其他方法,比如对产品的管理之类的操作。不仅仅是类,方法也是如此,每个方法专注一件事。

开闭原则

扩展开放,更改关闭。即不修改来扩展类的行为。比如通过继承接口来实现开闭原则,简单工厂和工厂方法的一个区别就是这样。

简单工厂设计模式

即使用一个工厂类来创建其他类的实例,通过switch根据不同参数返回不同的实例,其他类都有一个共同的父类。

有三个要素:

工厂:负责创建实例

抽象:即我们要创建的对象的父类

具体对象:我们需要创建的对象,即具体类的实例

其中:

1. 抽象出来的父类定义子类共有的方法

2. 子类的不同实现由自己完成

3. 工厂类用于创建实例对象,具体要创建哪个由传入的参数决定,可以通过switch判断。在这一步中,就不符合了开闭原则了。

    class Program
    {
        static void Main(string[] args)
        {
            Factory f = new Factory();
            f.CreateGun("pistol");
            f.CreateGun("rifle");

            Console.ReadKey();
        }
    }

    /// <summary>
    /// 父类枪
    /// </summary>
    public class Gun
    {

    }

    /// <summary>
    /// 步枪
    /// </summary>
    public class Rifle : Gun
    {
        public Rifle()
        {
            Console.WriteLine("步枪");
        }
    }

    /// <summary>
    /// 手枪
    /// </summary>
    public class Pistol : Gun
    {
        public Pistol()
        {
            Console.WriteLine("手枪");
        }
    }

    /// <summary>
    /// 工厂类
    /// </summary>
    public class Factory
    {
        public Gun CreateGun(string type)
        {
            // 因为这个switch使得简单工厂不符合开闭原则,很难扩展
            switch (type)
            {
                case "pistol":
                    return new Pistol();
                case "rifle":
                    return new Rifle();
                default:
                    throw new ArgumentException("暂无该项武器...");
            }
        }
    }

简单工厂主要问题就是扩展性很差,但需求改变时,比如增加具体的子类武器,我们需要创建一个新的子类并且继承父类,然后工厂类中也需要新增判断,这违背了开闭原则。业务简单或者需求变动少产品增加少的情况下简单工厂还是比较合适使用的,但是复杂的业务环境肯定就不是首选。

工厂方法模式

类的实例化由子类来决定。

和简单工厂不同:

1. 简单工厂只有一个工厂,实例化都在这个工厂中,通过传入参数判断,它可以创建所有的东西。而工厂方法有一个抽象的工厂和多个具体的工厂,每个具体的工厂创建对应的子类实例,实例化是在具体的工厂中实现的,所以扩展的时候很方便,不用修改switch里面的判断,只需要增加工厂即可。

2. 工厂方法符合开闭原则,简单工厂不符合。

要素:

1. 抽象产品

2. 具体产品

3. 抽象工厂(简单工厂没有抽象工厂)

4. 具体工厂

    class Program
    {
        static void Main(string[] args)
        {
            AbstractFactory f = new PistolFactory();
            f.Create();

            Console.ReadKey();
        }
    }
    /// <summary>
    /// 父类枪
    /// </summary>
    public class Gun
    {

    }

    /// <summary>
    /// 步枪
    /// </summary>
    public class Rifle : Gun
    {
        public Rifle()
        {
            Console.WriteLine("步枪");
        }
    }

    /// <summary>
    /// 手枪
    /// </summary>
    public class Pistol : Gun
    {
        public Pistol()
        {
            Console.WriteLine("手枪");
        }
    }

    /// <summary>
    /// 抽象工厂
    /// </summary>
    public interface AbstractFactory
    {
        /// <summary>
        /// 创建对象的接口方法
        /// </summary>
        /// <returns></returns>
        Gun Create();
    }

    /// <summary>
    /// 步枪的具体工厂
    /// </summary>
    public class RifleFactory : AbstractFactory
    {
        public Gun Create()
        {
            return new Rifle();
        }
    }

    /// <summary>
    /// 手枪的具体工厂
    /// </summary>
    public class PistolFactory : AbstractFactory
    {
        public Gun Create()
        {
            return new Pistol();
        }
    }

此时,如果增加了新的枪类,我们只需要增加具体的子类枪对象,继承抽象的父类,抽象工厂无需改动,再增加一个具体的工厂继承抽象工厂接口用来创建这个新产品即可。

说白了就是原有的代码无需修改,只需要添加,这一点符合开闭原则,引进新产品的时候非常的方便。

里氏转换原则

1)、子类可以赋值给父类(需要一个父类类型时,给一个子类类型的对象是可以的)

Person p1 = new Student();

2)、如果父类中装的是子类对象,那么可以将这个父类强转为这个子类对象。

Person p1 = new Student();
Student s1 = (Student)p1;

(不能把父类类型转换成子类对象):

Chinese c = (Chinese)new Person();	//是错的

我们子类继承了父类,就希望子类可以做父类的所有行为,并且自己可以扩展父类不能做的行为,实际上,子类并不一定都能做到父类的所有行为,例如鸭有吃的动作,但是玩具鸭不能吃,这个方法就违反了里氏转换原则。解决方法是可以使用接口,这样所有的鸭继承Duck,有吃的动作的鸭继承接口IDuckEat,玩具鸭直接继承Duck即可。

接口隔离原则

客户端不应该依赖它不需要的接口。一个类对另一个类的依赖应该建立在最小的接口上。说白了,一个通用的庞大接口并不一定是好事,将行为细分,多个不同的接口反而更容易保证接口隔离。

例如集合都继承了IEnumerable或者它的泛型,但是并不是所有的方法都集成在了这个接口中,一些不通用的方法我们可以放到其他子接口中,这样选择性的继承父接口或者子接口来保证接口隔离。例如很多集合都可以Insert和RemoveAt,但是Stack和Queue不能随便插入删除的,这时Insert和RemoveAt定义在了IEnumerable的子类ICollection的子类IList中,这时如果还存在其他集合可以随便插入删除的继承自IList,而Stack和Queue继承自ICollection。

依赖倒转原则

将抽象的类定义为一组接口,具体的实现以来这些接口。即高层不依赖于底层,他们都依赖的是那一组接口,即抽象。

例如我们有一台计算机,计算机有显示器,键盘等,那我们将所有的显示器都继承自IDisplay接口,所有的键盘继承自IkeyBoard接口,这样构造函数Computer(IDisplay display, IKeyBoard keyboard)中,不同品牌电脑当有不同的显示器键盘时,传入他们特定的显示器键盘即可,这就时依赖一组抽象接口,底层的显示器键盘则依赖对应的接口,所以说两个依赖的都是接口,一组抽象。将具体类型的显示器键盘通过构造函数传入给一个具体类型的电脑就是构造函数依赖注入。倘若你电脑定义时依赖的是具体的显示器键盘,后期将无法更改显示器和键盘的类型了。

依赖注入对需求的改变,功能的扩展等都更加灵活,模块间的耦合程度降低。

相关推荐

4万多吨豪华游轮遇险 竟是因为这个原因……

(观察者网讯)4.7万吨豪华游轮搁浅,竟是因为油量太低?据观察者网此前报道,挪威游轮“维京天空”号上周六(23日)在挪威近海发生引擎故障搁浅。船上载有1300多人,其中28人受伤住院。经过数天的调...

“菜鸟黑客”必用兵器之“渗透测试篇二”

"菜鸟黑客"必用兵器之"渗透测试篇二"上篇文章主要针对伙伴们对"渗透测试"应该如何学习?"渗透测试"的基本流程?本篇文章继续上次的分享,接着介绍一下黑客们常用的渗透测试工具有哪些?以及用实验环境让大家...

科幻春晚丨《震动羽翼说“Hello”》两万年星间飞行,探测器对地球的最终告白

作者|藤井太洋译者|祝力新【编者按】2021年科幻春晚的最后一篇小说,来自大家喜爱的日本科幻作家藤井太洋。小说将视角放在一颗太空探测器上,延续了他一贯的浪漫风格。...

麦子陪你做作业(二):KEGG通路数据库的正确打开姿势

作者:麦子KEGG是通路数据库中最庞大的,涵盖基因组网络信息,主要注释基因的功能和调控关系。当我们选到了合适的候选分子,单变量研究也已做完,接着研究机制的时便可使用到它。你需要了解你的分子目前已有哪些...

知存科技王绍迪:突破存储墙瓶颈,详解存算一体架构优势

智东西(公众号:zhidxcom)编辑|韦世玮智东西6月5日消息,近日,在落幕不久的GTIC2021嵌入式AI创新峰会上,知存科技CEO王绍迪博士以《存算一体AI芯片:AIoT设备的算力新选择》...

每日新闻播报(September 14)_每日新闻播报英文

AnOscarstatuestandscoveredwithplasticduringpreparationsleadinguptothe87thAcademyAward...

香港新巴城巴开放实时到站数据 供科技界研发使用

中新网3月22日电据香港《明报》报道,香港特区政府致力推动智慧城市,鼓励公私营机构开放数据,以便科技界研发使用。香港运输署21日与新巴及城巴(两巴)公司签署谅解备忘录,两巴将于2019年第3季度,开...

5款不容错过的APP: Red Bull Alert,Flipagram,WifiMapper

本周有不少非常出色的app推出,鸵鸟电台做了一个小合集。亮相本周榜单的有WifiMapper's安卓版的app,其中包含了RedBull的一款新型闹钟,还有一款可爱的怪物主题益智游戏。一起来看看我...

Qt动画效果展示_qt显示图片

今天在这篇博文中,主要实践Qt动画,做一个实例来讲解Qt动画使用,其界面如下图所示(由于没有录制为gif动画图片,所以请各位下载查看效果):该程序使用应用程序单窗口,主窗口继承于QMainWindow...

如何从0到1设计实现一门自己的脚本语言

作者:dong...

三年级语文上册 仿写句子 需要的直接下载打印吧

描写秋天的好句好段1.秋天来了,山野变成了美丽的图画。苹果露出红红的脸庞,梨树挂起金黄的灯笼,高粱举起了燃烧的火把。大雁在天空一会儿写“人”字,一会儿写“一”字。2.花园里,菊花争奇斗艳,红的似火,粉...

C++|那些一看就很简洁、优雅、经典的小代码段

目录0等概率随机洗牌:1大小写转换2字符串复制...

二年级上册语文必考句子仿写,家长打印,孩子照着练

二年级上册语文必考句子仿写,家长打印,孩子照着练。具体如下:...

一年级语文上 句子专项练习(可打印)

...

亲自上阵!C++ 大佬深度“剧透”:C++26 将如何在代码生成上对抗 Rust?

...

取消回复欢迎 发表评论: