Open-closed principle

開閉原則(Open-closed principle):開閉原則指的是類(Class)要可以對外擴展(open for extension),但是對內部修改封閉(closed for modification)。簡單的說就是可以為你的程式添加新的行為,但是不去修改現有程式碼。

一個經典的例子是計算體積,我們要建立一個 AreaCalculator 類,用來計算物體的體積,

下面是一個不遵守開閉原則的例子。

  • 定義了一個AreaCalculator類,它含有GetRectangleAreaGetCircleArea方法,分別用來計算四邊形與圓形的體積
  • 定義了一個Rectangle類,用來存放四邊形的寬和高
  • 定義了一個Circle類,用來存放圓形半徑
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    public class AreaCalculator
    {
    public float GetRectangleArea(Rectangle rectangle)
    {
    return rectangle.width * rectangle.height;
    }
    public float GetCircleArea(Circle circle)
    {
    return circle.radius * circle.radius * Mathf.PI;
    }
    }

    public class Rectangle
    {
    public float width;
    public float height;
    }

    public class Circle
    {
    public float radius;
    }
    這個AreaCalculator類是可以運作的如預期,但是如果添加更多計算體積的方法(例如三角形或五邊形),就會一直變更這個AreaCalculator類,這違反了開閉原則。

建立一個Shape基類,

1
2
3
4
public abstract class Shape
{
public abstract float CalculateArea();
}

所有物體皆繼承這個Shape基類

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Rectangle : Shape
{
public float width;
public float height;
public override float CalculateArea()
{
return width * height;
}
}

public class Circle : Shape
{
public float radius;
public override float CalculateArea()
{
return radius * radius * Mathf.PI;
}
}

AreaCalculator類更改為依賴Shape

1
2
3
4
5
6
7
public class AreaCalculator
{
public float GetArea(Shape shape)
{
return shape.CalculateArea();
}
}

如此每當添加新物體時,也不用更改AreaCalculator類,只需要新增一個繼承Shape的類即可

評論