iT邦幫忙

0

物件導向程式設計 : 開閉原則(OCP)

開閉原則 The Open/Closed Principle (OCP)

開閉原則規定「軟體中的對象(類,模塊,函數等等)應該對於擴展是開放的,但是對於修改是封閉的」,這意味著一個實體是允許在不改變它的原始碼的前提下變更它的行為。該特性在產品化的環境中是特別有價值的。

簡單來說 : 當對原有程式進行擴展時,在不更動到原始碼的前提完成擴展。

開 : 開放擴展

閉 : 封閉修改

如果要寫一隻複用性高的程式,或是將軟體產品化,遵守開閉原則將會輕鬆很多。

以下範例

    //產品:三角形
    public class Triangle 
    {
        public static void Show()
        {
            Console.WriteLine($"這是一個 Triangle ");
        }
    }
    //產品:方形
    public class Square 
    {
        public static void Show()
        {
            Console.WriteLine($"這是一個 Square ");
        }
    }
    //實作方法
    public class Display
    {
        public void ShowTheSharp(string sharp)
        {
            if (sharp == "Square")
            {
                Square square = new Square();
                square.Show();
            }
            else if (sharp == "Triangle")
            {
                Triangle triangle = new Triangle();
                triangle.Show();
            }
        }
    }

現在的實作方法是在Display中做判斷,此時當要新增一個新的形狀(圓形)時,就必須修改實作類別,而之後每次新增一個形狀就要再改一次。如下圖

    //新增 產品:圓形
    public class Circle 
    {
        public static void Show()
        {
            Console.WriteLine($"這是一個 Circle ");
        }
    }
    //實作方法
    public class Display
    {
        public void ShowTheSharp(string sharp)
        {
            
            if (sharp == "Square")
            {
                Square square = new Square();
                square.Show();
            }
            else if (sharp == "Triangle")
            {
                Triangle triangle = new Triangle();
                triangle.Show();
            }
            //////新增判斷//////
            else if (sharp == "Circle")
            {
                Circle circle = new Circle();
                circle.Show();
            }
        }
    }

這樣的情形就違反了開閉原則,所以維護起來也相對費力。
而解決方法呢,就是使用依賴注入(DI)的方法來重構此程式,為了滿足開閉原則,需要對系統進行抽象化(abstract)設計。

抽象化是開閉原則的關鍵而依賴注入則是實現開閉原則的方法。

新增一個抽象類別Sharp並讓其他形狀類別繼承此抽象類別。而實作方法Display則直接調用Sharp,讓Client端決定要輸入哪種形狀。這樣就達到開閉原則了,往後就算再新增形狀也不需要修改實作方法。

 public abstract class Sharp
    {
        public virtual void Show() { }
    }

    public class Triangle : Sharp 
    {
        public override void Show()
        {
            Console.WriteLine($"這是一個 Triangle ");
        }
    }
    public class Square : Sharp
    {
        public override void Show()
        {
            Console.WriteLine($"這是一個 Square ");
        }
    }
    public class Circle : Sharp
    {
        public override void Show()
        {
            Console.WriteLine($"這是一個 Circle ");
        }
    }

    public class Display 
    {
        public Sharp sharp;
        //依賴注入
        public void SetSharp(Sharp _sharp)
        {
            this.sharp = _sharp;
        }
        public void ShowTheSharp()
        {
            this.sharp.Show();
            //if (sharp == "Square")
            //{
            //    Square square = new Square();
            //    square.Show();
            //}
            //else if (sharp == "Triangle")
            //{
            //    Triangle triangle = new Triangle();
            //    triangle.Show();
            //}
            //else if (sharp == "Circle")
            //{
            //    Circle circle = new Circle();
            //    circle.Show();
            //}
        }
    }

總結

遵守開閉原則,是為了更有效的因應變化,未來的需求一定會不斷增加,而遵守開閉原則能降低維護的複雜度。

資料參考

https://blog.csdn.net/lovelion/article/details/7537584
https://zh.wikipedia.org/wiki/%E5%BC%80%E9%97%AD%E5%8E%9F%E5%88%99
https://www.zhihu.com/question/32108444


尚未有邦友留言

立即登入留言