一个小例子解释什么是面向面向对象编程

什么是面向对象的编程?其实这是一个很抽象的概念。如果讲术语的话,需要解释很多,也很难去理解。那就通过一个简单的例子,去演示一下什么是面向对象编程。

1、简单的功能

假设,PM要你做一个导出到Excel的功能。

很自然,我们会定义一个 ExportService 这样的类:

 public class ExportService
 {
     public void Export()
     {
         //导出Excel的逻辑
         Console.WriteLine("export to excel");
     }
 }

紧接着,我们在Main函数中,实例化这个对象,然后调用Export(),运行一下就完成了导出excel的功能。

partial class Program
{
    private static readonly ExportService exportService = new ExportService();
    static void Main(string[] args)
    {
        exportService.Export();
        //========================================
        Console.WriteLine("ok");
        Console.ReadLine();
    }
}

但是,PM某一天,又说,这个地方要改一下。我们需要一个导出到PDF的功能。

那也很简单,我们只需要修改一下ExportService这个类中的Export方法:

public class ExportService
{
    public void Export()
    {
        //导出pdf的逻辑
        Console.WriteLine("export to pdf");
    }
}

但是这样不好,违背了  对修改封闭,对扩展开放的一个原则。

2、扩展

为了能实现面向对象的扩展能力,那么我们需要对导出进行抽象。

自然,我们会来定一个接口:

 public interface IExport
 {
     void Export();
 }

接着,我们来实现我们的接口:

 public class ExportToExcel : IExport
 {
     public void Export()
     {
         Console.WriteLine("export to excel");
     }
 }

 public class ExportToPdf : IExport
 {
     public void Export()
     {
         Console.WriteLine("export to pdf");
     }
 }

所以,在ExportService这个类中,我们需要接收一个 IExport类型的对象。我们需要修改一下ExportService这个类

 public class ExportService
 {
     private IExport _export;

     public ExportService(IExport export)
     {
         _export = export;
     }

     public void Export()
     {
         //导出
         _export.Export();
     }
 }

然后,在实例化对象的时候,传入一个IExport类型的参数,比如要导出Excel,我们只需要传入一个ExportToExcel的实例即可:

private static readonly ExportService exportService = new ExportService(new ExportToExcel());

 

 同样,如果想导出到Pdf,这个地方传入一个ExportToPdf的实例即可。

这样,我们就可以不断去扩展其他导出,比如word,txt等。然后值需要在实例化的时候,传入对应的实例即可。

但是这个也不是终点。

3、IOC

我们还可以借助IOC来实现。

首先,我们可以将我们所有的服务注册到我们IOC容器中去,这里就使用dot net core下自带的容器去进行实现:

partial class Program
{
    //private static readonly ExportService exportService = new ExportService(new ExportToPdf());
    private static IServiceProvider serviceProvider;
    static void Main(string[] args)
    {
        RegisterService();
        var exportService = serviceProvider.GetRequiredService<ExportService>();//Get service of type T from the System.IServiceProvider.
        exportService.Export();
        //========================================
        Console.WriteLine("ok");
        Console.ReadLine();
    }

    /// <summary>
    /// 注册服务
    /// </summary>
    static void RegisterService()
    {
        var service = new ServiceCollection();//Microsoft.Extensions.DependencyInjection
        service.AddTransient<ExportService>();
        service.AddTransient<IExport, ExportToExcel>();
        serviceProvider = service.BuildServiceProvider();
    }
}

我们来运行一下程序:

 可以看到,我们成功的导出到了excel。

比如我们需要一个导出到txt的功能:

public class ExportToTxt : IExport
{
    public void Export()
    {
        Console.WriteLine("export to txt");
    }
}

我们只需要将这个导出到txt的服务注册到容器中即可:

 /// <summary>
 /// 注册服务
 /// </summary>
 static void RegisterService()
 {
     var service = new ServiceCollection();//需要引入Microsoft.Extensions.DependencyInjection
     service.AddTransient<ExportService>();
     service.AddTransient<IExport, ExportToExcel>();
     service.AddTransient<IExport, ExportToTxt>();
     serviceProvider = service.BuildServiceProvider();
 }

我们再来运行下程序看看:

 

 这样我们就可以进行对导出到不同文档的功能进行扩展了。

 这个地方,我们注册了txt和excel的服务,为什么只导出了txt?是因为,在同类型中,后面的会替换前面的,所以拿到的实例是最后加入的ExportToTxt。

还有一个IServiceProvider.GetServices。注释为:Get an enumeration of services of type T from the System.IServiceProvider。

这个扩展是可以每局出类型注册的所有服务。如果获取的是单一服务,优先级最高的是最后加入的。

 

posted @ 2020-11-17 00:13  冰乐  阅读(591)  评论(0编辑  收藏  举报