設計模式的六大原則

孤沉發表於2024-07-02

1、依賴倒置原則

/// <summary>
/// 高層模組不應該依賴底層模組
/// 二者都應該依賴其抽象
/// </summary>
public class Student
{
    public int Age { get; set; }
    public string Name { get; set; }
    public double Scores { get; set; }

    public void GetAge()
    {
        Age = 18;
        Console.WriteLine(Age);
    }

    /// <summary>
    /// 假如要增加一個GetName方法,你在原有的類上增加,
    /// 你這個看起來簡單,你覺得自己能hold住,實際上,牽一髮而動全身
    /// 真正已經執行的程式,你新增新的功能可能會出問題
    /// </summary>
    public void GetName()
    {
        Name = "張三";
        Console.WriteLine(Name);
    }
}

/// <summary>
/// 最好的解決方案就是增加一個介面
/// </summary>
public interface IStudent
{
    void GetName();
}

public class StudentExtend : IStudent
{
    public int Age { get; set; }
    public string Name { get; set; }
    public double Scores { get; set; }

    public void GetAge()
    {
        Age = 18;
        Console.WriteLine(Age);
    }

    public void GetName()
    {
        Name = "張三";
        Console.WriteLine(Name);
    }
}

依賴倒置原則:依賴倒置原則是SOLID設計原則中的"D",它建議程式碼應該依賴於抽象(介面或抽象類),而不是具體的實現。這樣做可以降低模組間的耦合度,提高程式碼的靈活性和可擴充套件性。

原始 Student 類:在原始的 Student 類中,GetAge 和 GetName 方法是直接在這個類中實現的。如果這個類已經被許多客戶端程式碼使用,那麼在未來對它的任何更改都可能影響到這些客戶端。

新增介面 IStudent:透過定義一個介面 IStudent 幷包含 GetName 方法,您建立了一個抽象層。這個介面可以被不同的類實現,而不影響現有的客戶端程式碼。

擴充套件 StudentExtend 類:StudentExtend 類實現了 IStudent 介面,這意味著它提供了介面中定義的方法的具體實現。這樣,如果未來需要新增更多方法,您可以在不修改原始 Student 類的情況下進行。

解耦和靈活性:使用介面作為中介,StudentExtend 類的實現與使用它的客戶端程式碼解耦。客戶端程式碼只需要知道 IStudent 介面,而不需要知道具體的實現類。這使得更換或擴充套件實現變得更加容易。

開閉原則:透過依賴介面,您的設計遵循了開閉原則,即軟體實體應對擴充套件開放,對修改封閉。這意味著您可以在不改變現有程式碼的基礎上增加新功能。

實際應用:在實際的應用程式中,如果需要對 Student 類新增新的行為,您可以透過定義新的介面和實現這些介面的類來擴充套件功能,而不影響現有的使用 Student 類的程式碼。
2、介面隔離原則

/// <summary>
/// 介面隔離原則有點像單一職責,但是還是要防止封裝過度
/// </summary>
public interface IPhone
{
    void GetNumber();// 獲取電話號碼
    void SendContent();//傳送簡訊
    void Call(); //打電話
    void PlayGame();//打遊戲
}

public class Phone : IPhone
{
    public void GetNumber()
    {
        Console.WriteLine("獲取電話號碼");
    }

    public void SendContent()
    {
        Console.WriteLine("傳送簡訊");
    }

    public void Call()
    {
        Console.WriteLine("打電話");
    }

    public void PlayGame()
    {
        Console.WriteLine("打遊戲");
    }
}

/// <summary>
/// 如果只有一部需要打電話、傳送簡訊的老年機,畢竟老年人不玩遊戲,這個時候,介面應該隔離
/// </summary>
public interface IPhoneExtend1
{
    void SendContent();//傳送簡訊
    void Call(); //打電話
}
public interface IPhoneExtend2
{
    void GetNumber();// 獲取電話號碼
    void PlayGame();//打遊戲
}

/// <summary>
/// 老年手機
/// </summary>
public class Phone1 : IPhoneExtend1
{
    public void SendContent()
    {
        Console.WriteLine("傳送簡訊");
    }

    public void Call()
    {
        Console.WriteLine("打電話");
    }
}

/// <summary>
/// 學生手機
/// </summary>
public class Phone2 : IPhoneExtend1,IPhoneExtend2
{
    public void GetNumber()
    {
        Console.WriteLine("獲取電話號碼");
    }

    public void SendContent()
    {
        Console.WriteLine("傳送簡訊");
    }

    public void Call()
    {
        Console.WriteLine("打電話");
    }

    public void PlayGame()
    {
        Console.WriteLine("打遊戲");
    }
}

3、迪米特原則

/// <summary>
/// 迪米特原則,最少知道原則
/// 團隊的組長知道專案進度
/// 老闆也要知道專案進度
/// 專案進度組長直接告訴老闆就行
/// 所以正確的寫法應當是專案進度的類暴露給團隊組長
/// 再由團隊組長告知老闆,專案進度這個類不需要出現在老闆的類中
/// </summary>
public class Sample {
    public static void GetProcess() {
        Boss boss = new Boss();
        TeamLeader teamLeader = new TeamLeader();
        boss.CommandTeamLeader(teamLeader);
    }
}

public class Boss{
    public void CommandTeamLeader(TeamLeader teamLeader) {
//	    teamLeader.sayProccess(new Program());
        teamLeader.SayProccess();
    }
}

public class TeamLeader{
    //void sayProccess(Program program) {
    //    program.getProccess();
    //}
    public void SayProccess() {
        new Program().GetProccess();
    }
}

public class Program{

    public void GetProccess() {
        Console.WriteLine("當前的專案進度為  50%");
    }
}

4、里氏替換原則

/// <summary>
/// 1、現在學生類只有一個方法,獲取學生成績
/// 2、現在進行擴充套件,新增一個功能,
/// 3、我們只需要獲取理科成績
/// </summary>
public class Student
{
    public int Age { get; set; }
    public string Name { get; set; }
    public double Scores { get; set; }

    /// <summary>
    /// 獲取學生成績
    /// </summary>
    /// <returns></returns>
    public double GetScores()
    {
        return Scores;
    }

    //獲取理科成績
    public double GetScienceScore()
    {
        return Scores;
    }
}

/// <summary>
/// 現在擴充套件一個功能,由子類完成
/// 這個功能在原來的GetScores上新增
/// 那麼,這個擴充套件的方法可能導致原有的方法發生故障
/// 解決方法,儘量不要過載、重寫父類方法
/// </summary>
public class StudentExtend : Student
{
    public double NewScores()
    {
        return default;
    }
}

/// <summary>
/// 理科
/// </summary>
public class ScienceStudent : Student
{
    public double GetScienceScore()
    {
        return Scores;
    }
}

/// <summary>
/// 文科
/// </summary>
public class VincoStudent : Student
{
    public double GetVincoScore()
    {
        return Scores;
    }
}

5、開閉原則

public interface IStudent
{
    void GetStudent();
    
}

public class Student:IStudent
{
    public void GetStudent()
    {
         
    }
}

///簡單來說就是對擴充套件開放,對修改關閉
IStudent stu=new Student();
stu.GetStudent();

//你可以重新寫一個類去實現IStudent,而不要去修改IStudent和Student

6、單一職責原則

/// <summary>
/// 一個類只負責一項職責,就一個類而言,只有一個引起它變化的原因
/// </summary>
public class Sample
{
    /// <summary>
    /// 簡單來說就是各司其職
    /// 不要讓一個類有太多的功能
    /// 多寫一個抽象類分離出去
    /// 使用繼承去分門別類
    /// </summary>
    public class Student
    {
        public int Age { get; set; }
        public string Name { get; set; }
        public double Scores { get; set; }
        public Student()
        {
            
        }

        /// <summary>
        /// 獲取學生成績
        /// </summary>
        /// <returns></returns>
        public double GetScores()
        {
            return Scores;
        }
    }
    
}

相關文章