开闭原则的含义是:
对扩展开放,对修改关闭
。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。
想要达到热插拔的效果,我们需要进行抽象(接口和抽象类)。因为抽象灵活性好,适应性广,只要抽象的合理,可以基本保持软件架构的稳定。而软件中易变的细节可以从抽象派生来的实现类来进行扩展,当软件需要发生变化时,只需要根据需求重新派生一个实现类来扩展就可以了。
1 案例分析(输入法皮肤)
搜狗输入法的皮肤是输入法背景图片、窗口颜色和声音等元素的组合。用户可以根据自己的喜爱更换输入法的皮肤。这些皮肤有共同的特点,可以为其定义一个抽象类(AbstractSkin),而每个具体的皮肤(DefaultSkin和CustomSkin)是其子类。用户窗体可以根据需要选择或者增加新的主题,而不需要修改原代码,所以它是满足开闭原则的。
using System;
namespace DesignPattern
{
internal static class Program
{
public static void Main(string[] args)
{
// 定义输入法的一个实例,使用默认皮肤进行初始化
var souGouInput = new SouGouInput { Skin = new DefaultSkin() };
// 显示当前使用的皮肤
souGouInput.Display();
Console.WriteLine("---------------------------------------");
Console.WriteLine("开始切换皮肤");
// 切换为自定义皮肤
souGouInput.Skin = new CustomSkin();
// 显示当前使用的皮肤
souGouInput.Display();
}
}
/// <summary>
/// 输入法皮肤的抽象基类
/// </summary>
public abstract class AbstractSkin
{
/// <summary>
/// 用于显示当前所使用的皮肤
/// </summary>
public abstract void Display();
}
/// <summary>
/// 默认皮肤
/// </summary>
public class DefaultSkin : AbstractSkin
{
/// <summary>
/// <inheritdoc cref="AbstractSkin"/>
/// </summary>
public override void Display()
{
Console.WriteLine(nameof(DefaultSkin));
}
}
/// <summary>
/// 自定义皮肤
/// </summary>
public class CustomSkin : AbstractSkin
{
/// <summary>
/// <inheritdoc cref="AbstractSkin"/>
/// </summary>
public override void Display()
{
Console.WriteLine(nameof(CustomSkin));
}
}
/// <summary>
/// 搜狗输入法类
/// </summary>
public class SouGouInput
{
/// <summary>
/// 皮肤抽象积累的成员变量
/// </summary>
public AbstractSkin Skin {get;set;}
/// <summary>
/// 用于显示当前所使用的皮肤
/// </summary>
public void Display()
{
Skin?.Display();
}
}
}