c# - 关于依赖注入(inject),何时使用抽象类与接口(interface)?

标签 c# .net oop design-patterns

我一直在阅读一些关于 SOLID 原则和依赖倒置的文章。从我的角度来看,我必须使用一个接口(interface)来与任何类对话。我的类(class)正在使用界面聊天。

第一个问题:

我使用的是抽象类,但对于代码的第二部分,我使用的是接口(interface)。

用法1


namespace DependencyInjection
{

    public interface IMessage
    {

    }
    public abstract class Message
    {
        public abstract void Get();
        public abstract void Send();
    }

    public class Sms : Message, IMessage
    {
        public override void Get()
        {
            Console.WriteLine("Message Get!");
        }
        public override void Send()
        {
            Console.WriteLine("Message Send!");
        }
    }

    public class MessageManager
    {
        private IMessage _message;

        public Sms Sms
        {
            get { return _message as Sms; }
            set { _message = value; }
        }

        public MessageManager(IMessage message)
        {
            _message = message;
        }

    }
}

用法:



    class Program
    {
        static void Main(string[] args)
        {
            MessageManager msg = new MessageManager(new Sms());
            msg.Sms.Get();
            msg.Sms.Send();
            Console.Read();
        }
    }

用法2


namespace DependencyInjection
{

    public interface IMessage
    {
        public  void Get();
        public  void Send();
    }


    public class Sms :  IMessage
    {
        public  void IMessage.Get()
        {
            Console.WriteLine("Message Get!");
        }
        public  void IMessage.Send()
        {
            Console.WriteLine("Message Send!");
        }
    }

    public class MessageManager
    {
        private IMessage _message;

        public Sms Sms
        {
            get { return _message as Sms; }
            set { _message = value; }
        }

        public MessageManager(IMessage message)
        {
            _message = message;
        }

    }
}

Usage1 和 usage2 有什么区别?什么时候选择用法 1 或用法 2?

最佳答案

此处的抽象类与重复代码作斗争。接口(interface) - 定义契约 (API)。

依赖于接口(interface) - 它们只是描述依赖关系的契约 (API),并且它们可以很容易地被模拟。所以,从界面开始:

public interface IMessage
{
    void Get(); // modifiers like public are not allowed here
    void Send();
}

这是你的依赖类,它应该只依赖于抽象(即接口(interface)):

public class MessageManager
{
    private IMessage _message;

    // depend only on abstraction 
    // no references to interface implementations should be here
    public IMessage Message
    {
        get { return _message; }
        set { _message = value; }
    }

    public MessageManager(IMessage message)
    {
        _message = message;
    }
}

然后创建类,它将实现您的接口(interface):

public class Sms : IMessage
{
    // do not use explicit implementation 
    // unless you need to have methods with same signature
    // or you want to hide interface implementation
    public void Get()
    {
        Console.WriteLine("Message Get!");
    }

    public void Send()
    {
        Console.WriteLine("Message Send!");
    }
}

现在您已经反转了依赖关系 - MessageManagerSms 仅依赖于 IMessage。您可以将任何 IMessage 实现注入(inject)到 MessageManager(MessageManager 现在适合 OCP - 对扩展开放,但对修改关闭)。

当您在多个 IMessage 实现程序中有重复代码时,创建基础抽象消息类。当你创建抽象类(地方,你移动重复代码的地方)时,你不应该改变接口(interface),因为契约(Contract)保持不变。只需从原始 IMessage 接口(interface)继承您的基类。

关于c# - 关于依赖注入(inject),何时使用抽象类与接口(interface)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13442312/

相关文章:

c# - 无需完整下载即可读取 zip 文件

python - 构建应用程序 : Is it bad form to have an app create directories on users computer for program file storage?

java - 从 Iterable 计算 SumOfInts

c# - 使用起始值对对象列表进行排序的最佳方法是什么?

c# - 将 Matlab 代码集成到 C# 应用程序中

c# - 将文件上传到 Amazon S3 中的存储桶失败并显示 "Maximum number of retry attempts reached"

java - 如何在 C++ 或 Java 中管理大量接口(interface)

c# - NLog 和单元测试

C# 从路径中剪切文件名

c# - 为什么使用 Lockbits 编辑图像仍然需要 7 秒?