0x05、设计模式原则 —— 开闭原则

开闭原则(Open Closed Principle) 是编程中最基础、最重要的设计原则

一个软件实体,比如:类,模块和函数应该对扩展开放(对提供方而言), 对修改关闭(对使用方而言)。 用抽象构建框架,用实现扩展细节

当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。

编程中遵循其它原则,以及使用设计模式的目的就是遵循开闭原则。

 

演示

假设有如下UML类图,Retangle矩形类 和 Circle圆形类 继承至 Shape;

 

 上图代码实现:

public static void Main(string[] args)
{
    GraphicEditor graphicEditor = new GraphicEditor();
    graphicEditor.drawShape(new Rectangle());
    graphicEditor.drawShape(new Circle());
}

/// <summary>
/// 绘制操作【使用方】
/// </summary>
class GraphicEditor
{
    public void drawShape(Shape s)
    {
        if (s.m_type == 1)
            drawRectangle(s);
        else if (s.m_type == 2)
            drawCircle(s);
    }
    public void drawRectangle(Shape r)
    {
        Console.WriteLine(" 绘制矩形 ");
    }
    public void drawCircle(Shape r)
    {
        Console.WriteLine(" 绘制圆形 ");
    }
}

/// <summary>
/// 图形 基类
/// </summary>
public class Shape
{
    public int m_type;
}

/// <summary>
/// 矩形类
/// </summary>
public class Rectangle : Shape
{
    public Rectangle()
    {
        m_type = 1;
    }
}

/// <summary>
/// 圆形类
/// </summary>
public class Circle : Shape
{
    public Circle()
    {
        m_type = 2;
    }
}

上面代码中,违反了设计模式的ocp原则(对扩展开放(提供方),对修改关闭(使用方))。即当我们给类增加新功能的时候,尽量不修改代码,或者尽可能少修改代码;

比如我们这时要新增加一个图形种类 三角形,我们需要做如下修改, 修改的地方较多:

public static void Main(string[] args)
{
    GraphicEditor graphicEditor = new GraphicEditor();
    graphicEditor.drawShape(new Rectangle());
    graphicEditor.drawShape(new Circle());
    graphicEditor.drawShape(new Trianle());         // 新增!!
}

/// <summary>
/// 绘制操作【使用方】
/// </summary>
class GraphicEditor
{
    public void drawShape(Shape s)
    {
        if (s.m_type == 1)
            drawRectangle(s);
        else if (s.m_type == 2)
            drawCircle(s);
        else if (s.m_type == 3)        // 使用方这里新增一个判断!!!(即修改了使用方)
            drawTrianle(s);
    }
    public void drawRectangle(Shape r)
    {
        Console.WriteLine(" 绘制矩形 ");
    }
    public void drawCircle(Shape r)
    {
        Console.WriteLine(" 绘制圆形 ");
    }
    public void drawTrianle(Shape r)        // 使用方这里新增一个方法!!!(即修改了使用方)
    {
        Console.WriteLine(" 绘制三角形 ");
    }
}

/// <summary>
/// 图形 基类
/// </summary>
public class Shape
{
    public int m_type;
}

/// <summary>
/// 矩形类
/// </summary>
public class Rectangle : Shape
{
    public Rectangle()
    {
        m_type = 1;
    }
}

/// <summary>
/// 圆形类
/// </summary>
public class Circle : Shape
{
    public Circle()
    {
        m_type = 2;
    }
}

/// <summary>
/// 三角形类
/// </summary>
public class Trianle : Shape        // 新增!!!
{
    public Trianle()
    {
        m_type = 3;
    }
}

上面只是扩充了一个三角形,就需要改动【使用方】的代码,这违背了 开闭原则,我们怎么改进它呢?

改进方式思路: 把Shape类做成抽象类,并提供一个抽象的draw方法,让子类去实现即可,这样我们有新的图形种类时,只需要让新的图形类继承Shape,并实现draw方法即可,使用方的代码就不需要修 -> 这样就满足了开闭原则~

即:

public static void Main(string[] args)
{
    GraphicEditor graphicEditor = new GraphicEditor();
    graphicEditor.drawShape(new Rectangle());
    graphicEditor.drawShape(new Circle());
    graphicEditor.drawShape(new Trianle());
}

/// <summary>
/// 绘制操作【使用方】
/// </summary>
class GraphicEditor
{
    public void drawShape(Shape s)
    {
        s.draw();
    }
}

/// <summary>
/// 图形 基类
/// </summary>
public abstract class Shape
{
    public int m_type;

    public abstract void draw();
}

/// <summary>
/// 矩形类
/// </summary>
public class Rectangle : Shape
{
    public Rectangle()
    {
        m_type = 1;
    }

    public override void draw()
    {
        Console.WriteLine(" 绘制矩形 ");
    }
}

/// <summary>
/// 圆形类
/// </summary>
public class Circle : Shape
{
    public Circle()
    {
        m_type = 2;
    }
    public override void draw()
    {
        Console.WriteLine(" 绘制圆形 ");
    }
}

/// <summary>
/// 三角形类
/// </summary>
public class Trianle : Shape
{
    public Trianle()
    {
        m_type = 3;
    }
    public override void draw()
    {
        Console.WriteLine(" 绘制三角形 ");
    }
}

修改成这样后,如果我们需要增加一个其他图形的话,那么 只是新增一个 OtherGraphic 类并在 Main 函数中调用即可:

public static void Main(string[] args)
{
    GraphicEditor graphicEditor = new GraphicEditor();
    graphicEditor.drawShape(new Rectangle());
    graphicEditor.drawShape(new Circle());
    graphicEditor.drawShape(new Trianle());
    graphicEditor.drawShape(new OtherGraphic());    // -- 新增
}

/// <summary>
/// 绘制操作【使用方】
/// </summary>
class GraphicEditor
{
    public void drawShape(Shape s)
    {
        s.draw();       // 不需要改动
    }
}

/// <summary>
/// 图形 基类
/// </summary>
public abstract class Shape
{
    public int m_type;

    public abstract void draw();
}

/// <summary>
/// 矩形类
/// </summary>
public class Rectangle : Shape
{
    public Rectangle()
    {
        m_type = 1;
    }

    public override void draw()
    {
        Console.WriteLine(" 绘制矩形 ");
    }
}

/// <summary>
/// 圆形类
/// </summary>
public class Circle : Shape
{
    public Circle()
    {
        m_type = 2;
    }
    public override void draw()
    {
        Console.WriteLine(" 绘制圆形 ");
    }
}

/// <summary>
/// 三角形 类
/// </summary>
public class Trianle : Shape
{
    public Trianle()
    {
        m_type = 3;
    }
    public override void draw()
    {
        Console.WriteLine(" 绘制三角形 ");
    }
}

/// <summary>
/// 其他形 类
/// </summary>
public class OtherGraphic : Shape    // -- 新增
{
    public OtherGraphic()
    {
        m_type = 4;
    }
    public override void draw()
    {
        Console.WriteLine(" 绘制其他形 ");
    }
}

这样,我们的代码就完美的实现了开闭原则了;

有木有发现,这个写法和之前的讲到的 依赖倒置原则 很像?

 

注意了,这个开闭原则很重要的,面试要考的~~而且,也不难啊~~加油,最后两个原则,下一章:迪米特法则

posted @ 2022-04-02 00:57  醉马踏千秋  阅读(88)  评论(0编辑  收藏  举报