【设计模式】依赖倒转原则(Dependence Inversion Principle)

本文通过组装电脑的例子,展示了依赖倒转原则的重要性。原本的设计中,高层模块(Computer类)直接依赖了低层模块(具体配件类),导致用户无法自由选择配件品牌。通过引入接口,将依赖改为对抽象的依赖,使得Computer类可以灵活地配置不同品牌的配件,降低了模块间的耦合,提高了代码的可扩展性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块间的耦合。

1 案例分析(组装电脑)

组装一台电脑,需要CPU,硬盘,内存条等配件。这些配件又各自具有多种品牌,例如,CPU有Intel与AMD,硬盘有择希捷与西数,内存条有金士顿与海盗船。

using System;

namespace DesignPattern
{
    internal static class Program
    {
        public static void Main(string[] args)
        {
            var c = new Computer
            {
                Cpu = new IntelCpu(),
                Memory = new KingstonMemory(),
                HardDisk = new XiJieHardDisk()
            };

            c.Run();
        }
    }
    
    public class Computer
    {
        /// <summary>
        /// Inter Cpu 属性
        /// </summary>
        public IntelCpu Cpu { get; set; }
        
        /// <summary>
        /// 金士顿 内存 属性
        /// </summary>
        public KingstonMemory Memory { get; set; }
        
        /// <summary>
        /// 希捷 硬盘 属性
        /// </summary>
        public XiJieHardDisk HardDisk { get; set; }

        /// <summary>
        /// 运行
        /// </summary>
        public void Run()
        {
            Console.WriteLine("运行计算机");
            var data = this.HardDisk.Get();
            Console.WriteLine("从硬盘上获取的数据是:" + data);
            this.Cpu.Run();
            this.Memory.Save();
        }
    }

    /// <summary>
    /// 希捷硬盘类
    /// </summary>
    public class XiJieHardDisk
    {
        /// <summary>
        /// 保存数据
        /// </summary>
        /// <param name="data">数据</param>
        public void Save(string data)
        {
            Console.WriteLine("使用希捷硬盘存储数据为:" + data);
        }

        /// <summary>
        /// 获取数据
        /// </summary>
        /// <returns>数据</returns>
        public string Get()
        {
            Console.WriteLine("使用希捷希捷硬盘取数据");
            return "数据";
        }
    }

    /// <summary>
    /// 金士顿内存类
    /// </summary>
    public class KingstonMemory
    {
        /// <summary>
        /// 保存数据
        /// </summary>
        public void Save()
        {
            Console.WriteLine("使用金士顿内存条");
        }
    }

    /// <summary>
    /// 因特尔CPU类
    /// </summary>
    public class IntelCpu
    {
        /// <summary>
        /// 运行
        /// </summary>
        public void Run()
        {
            Console.WriteLine("使用Intel处理器");
        }
    }
}

上面组装的电脑能够正常运行,但配件的品牌是固定的,不可以改变。如果用户想使用自己中意的品牌,则上述设计是不满足要求的。

2 案例改进

根据依赖倒转原则进行改进:只需要修改Computer类,让Computer类依赖抽象(各个配件的接口),而不是依赖于各个组件具体的实现类。

using System;

namespace DesignPattern
{
    internal static class Program
    {
        public static void Main(string[] args)
        {
            var c = new Computer()
            {
                Cpu = new IntelCpu(),
                Memory = new KingstonMemory(),
                HardDisk = new XiJieHardDisk()
            };

            c.Run();
        }
    }
    
    public class Computer
    {
        /// <summary>
        /// CPU属性
        /// </summary>
        public ICpu Cpu { get; set; }
        
        /// <summary>
        /// 内存属性
        /// </summary>
        public IMemory Memory { get; set; }
        
        /// <summary>
        /// 硬盘属性
        /// </summary>
        public IHardDisk HardDisk { get; set; }

        /// <summary>
        /// 运行
        /// </summary>
        public void Run()
        {
            Console.WriteLine("运行计算机");
            var data = this.HardDisk.Get();
            Console.WriteLine("从硬盘上获取的数据是:" + data);
            this.Cpu.Run();
            this.Memory.Save();
        }
    }
    
    /// <summary>
    /// 硬盘接口
    /// </summary>
    public interface IHardDisk
    {
        /// <summary>
        /// 保存数据
        /// </summary>
        /// <param name="data">数据</param>
        void Save(string data);
        
        /// <summary>
        /// 获取数据
        /// </summary>
        /// <returns>数据</returns>
        string Get();
    }

    /// <summary>
    /// 内存接口
    /// </summary>
    public interface IMemory
    {
        /// <summary>
        /// 保存
        /// </summary>
        void Save();
    }

    /// <summary>
    /// CPU接口
    /// </summary>
    public interface ICpu
    {
        /// <summary>
        /// 运行
        /// </summary>
        void Run();
    }

    /// <summary>
    /// 希捷硬盘类
    /// </summary>
    public class XiJieHardDisk : IHardDisk
    {
        /// <summary>
        /// <inheritdoc cref="IHardDisk"/>
        /// </summary>
        /// <param name="data">数据</param>
        public void Save(string data) => Console.WriteLine("使用希捷硬盘存储数据为:" + data);

        /// <summary>
        /// <inheritdoc cref="IHardDisk"/>
        /// </summary>
        /// <returns>数据</returns>
        public string Get()
        {
            Console.WriteLine("使用希捷希捷硬盘取数据");
            return "数据";
        }
    }

    /// <summary>
    /// 金士顿内存
    /// </summary>
    public class KingstonMemory : IMemory
    {
        /// <summary>
        /// 保存
        /// </summary>
        public void Save() => Console.WriteLine("使用金士顿内存条");
    }

    /// <summary>
    /// CPU
    /// </summary>
    public class IntelCpu : ICpu
    {
        /// <summary>
        /// 运行
        /// </summary>
        public void Run() => Console.WriteLine("使用Intel处理器");
    }
}

改进后,Computer类的成员HardDiskCpuMemory可以使用实现IHardDiskICpuIMemory接口的任意类型。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhy29563

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值