【C#】物件导向的六个原则

今天我们来看物件导向程序设计的六个原则~

原则可以把它视为是写程序的一种好习惯~

那我们来看看这六个好习惯分别是什麽呢?


学习目标: 物件导向六个原则的概念

学习难度: ☆☆☆


第一个是 单一职责 (Single Reponsibility Principle)

单一职责原则 故名思义就是一个类别只负责一个职责~

也就是说~ 我们要让一个类别指做一个行为~

进而让程序形成高内聚、低耦合的状态!

  public class GameProgrammer //游戏工程师使用游戏引擎
  {
      public void coding()
      {
          Console.WriteLine("I could used Unity to develop game");
      }
  }

第二个是开闭原则(Open Closed Principle)

开闭原则是指 当我们完成一个模组(类别、方法)时,就不要在对他进行修改。

也就是说,我们在设计程序时,要尽量用扩充的方式来新增功能,而要避免用修改程序的方式

    public interface IProgrammer  //工程师会写Code
    {
        public Name{get;set;}
        
        void coding();
    }
    
    public class GameProgrammer : IProgrammer //新增一个游戏工程师
    {
        public Name{get;set;}
    
        public void coding()
        {
             Console.WriteLine("I could used Unity to develop game");
        }
    }

    public class DataBaseProgrammer : IProgrammer //新增一个资料库工程师
    {
        public Name{get;set;}
    
        public void coding()
        {
             Console.WriteLine("I could used SQL to Maintain player's data");
        }
    }


第三个是依赖反转原则(Dependency-Inversion Principle)

依赖反转原则 是指高阶模组(类别、方法)不应依赖低阶模组(类别、方法)~它们都应该依赖抽象

另外~ 抽象不应该依赖於模组(类别、方法),模组(类别、方法)应该依赖抽象

简单来说~ 我们在设计程序时~ 要将架构设计在抽象~ 在让模组去继承抽象~

    public interface IProgrammer
    {
        public Name{get;set;}
    
        void coding();

        void debug();
    }

    public class GameProgrammer : IProgrammer
    {
        public Name{get;set;}
    
        public void coding()
        {
             Console.WriteLine("I could used Unity to develop game");
        }
        public void debug()
        {
             Console.WriteLine("I could debug unity program");
        }
    }

    public class Programmer
    {
        private IProgrammer iprogrammer;

        public Programmer(IProgrammer programmer)
        {
            iprogrammer = programmer;
        }

        public void coding()
        {
            iprogrammer.coding();
        }

        public void debug()
        {
            iprogrammer.debug();
        }
    }

    class MainProgram
    {
        static void Main()
        {
            IProgrammer i_gameProgrammer = new GameProgrammer();

            Programmer gameprogrammer = new Programmer(i_gameProgrammer);

            gameprogrammer.coding();

            gameprogrammer.debug();
        }
    }

第四个是里氏替换原则(Liskov Substitution Principle)

里氏替换原则是指子类别必须能够替换父类别~

同时子类别替换父类别後,不需要改变,也不会发生任何错误或异常。

最简单来说~ 父类别能做到的事情,子类别也要能做到~

    public abstract class Programmer
    {
        public abstract void coding();
    }
    
    public class GameProgrammer : Programmer
    {
        public override void coding()
        {
            Console.WriteLine("I could used Unity to develop game");
        }
    }
    
    public class DataBaseProgrammer : Programmer
    {
        public override void coding()
        {
            Console.WriteLine("I could used SQL to maintain data");
        }
    }
    
    class MainProgram
    {
        static void Main()
        {
            //因为父子类能替换,所以它们能这样实例化
        
            Programmer gameprogrammer = new GameProgrammer(); 
            
            gameprogrammer.coding();
            
             //因为父子类能替换,所以它们能这样实例化
            
            Programmer databaseprogrammer = new DataBaseProgrammer();
            
            databaseprogrammer.coding();
        }
    }

第五个是介面隔离原则(Interface Segregation Principle)

介面隔离原则的概念很简单~ 就很像是单一职责的介面版本~

我们不应该在介面放入许多不同的抽象方法~ 因为有些子类别可能会难以实作~

例如~ 我们在工程师的介面放入弹钢琴~ 但有些工程师可能不会弹钢琴~

因此~ 那些工程师的类别就难以实现弹钢琴的抽象方法~

所以~我们应该设计许多的介面~ 然後每个介面有它专精的抽象方法~

    public interface IProgrammer 
    {  
        void coding();
    }
    
    public interface IPianoPlayer 
    {  
        void playpiano();
    }

    public class GameProgrammer : IProgrammer, IPianoPlayer
    { 
        public void coding()
        {
             Console.WriteLine("I could used Unity to develop game");
        }
        public void playpiano()
        {
             Console.WriteLine("I could played piano");
        }
    }

第六个是最少知识原则(Least Knowledge Principle)

最少知识原则是指一个类别只和它相关的类别依赖~

因此~最少知识原则也要求~ 一个类别应对依赖的物件有最少的了解~

我们这次都用类别来举例~

    public class Customer
    {
        public Product product { get; set; }

        public Customer()
        {
            product = new Product();
        }

        public void Access()
        {
            product.factory.FactorySecret(); //尽量不要让顾客读到与它无关的资料~
        }
    }

    public class Product
    {
        public Factory factory { get; set; }

        public Product()
        {
            factory = new Factory();
        }
    }

    public class Factory
    {
        public void FactorySecret()
        {
            Console.WriteLine("This is a factory secret...");
        }
    }

    class MainProgram
    {
        static void Main()
        {
            Customer customer = new Customer();

            customer.Access(); //顾客能读到公司的秘密,很怪吧~
        }
    }

参考资料:

https://dotnettutorials.net/lesson/single-responsibility-principle/

https://www.c-sharpcorner.com/UploadFile/pranayamr/open-close-principle/

https://www.youtube.com/watch?v=CxsZFL6rj5c&ab_channel=anitakumari

https://dotnettutorials.net/lesson/liskov-substitution-principle/

https://dotnettutorials.net/lesson/interface-segregation-principle/

https://www.c-sharpcorner.com/article/the-law-of-demeter/


<<:  搞懂 P2P 技术 (3) - WebRTC x AWS x KVS

>>:  AWS Academy LMS 教材使用 - 教师

Day 24 - Spring Security (一) 基本概念与流程

Spring Security 是Spring 官方建议的验证框架,提供了安全性方面的解决方案,这个...

[Day2] CSS + JS Clock

[Day2] CSS + JS Clock 运用 CSS 和 Javascript 做一个虚拟时钟 ...

38.vue.config.js

有些针对 @vue/cli 的全局配置,例如你惯用的包管理器和你本地保存的 preset,都保存在 ...

Day 26: Insertion sort & Selection sort

我们先来用insertion sort algorithm来解题。 虽然他的效率也不高,但这是很好理...

Day26- Go with Scylla

前言 前一篇我们介绍了如何在 Go 中对 MySQL 做操作,而 MySQL 为关联式资料库,而今天...