如何仅使用合成来模拟虚拟方法?

时间:2018-11-08 14:42:30

标签: c# inheritance design-patterns polymorphism composition

我在始终使用组合的概念上苦苦挣扎,有很多文章提到几乎所有继承的使用都可以用组合代替。我知道它有诸如测试之类的好处...但是在这种情况下,如何替换继承的使用?

基本上,我有2个装饰器,它们向现有的文件服务类添加功能。在复制文件之前,我希望它重命名它们,然后委派回原始文件服务。

在此示例中,我有两种方法。一个循环通过理论上的文件列表,然后调用“复制文件”。装饰器类无需复制代码,而只需调用包装的实现版本,类似于利用继承。

但是,这不能像继承那样工作,因为现在它永远不会调用装饰器CopyFile方法,因为它现在在先前的基类实现中,它不知道装饰器CopyFile方法存在。

如果我使用继承,则通过将方法标记为虚方法,基类将知道何时重写其功能之一,并调用该版本而不是其版本。

如何仅使用合成来模仿此功能?

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp5
{

public interface IFileService
{
    void CopyFile(string source, string destination);
    void CopyFiles(IEnumerable<string> source, string destination);
}

public class MainFileService : IFileService
{
    public void CopyFile(string source, string destination)
    {
        Console.WriteLine("Base Method of Copy File invoked");
    }

    public void CopyFiles(IEnumerable<string> source, string destination)
    {
        foreach (var file in source)
        {
            CopyFile(file,destination);
        }
    }
}

public class RenamingFileService : IFileService
{
    private IFileService _wrapper;

    public RenamingFileService(IFileService wrapper)
    {
        this._wrapper = wrapper;
    }

    public void CopyFile(string source, string destination)
    {
        RenameFileExtensionToPART();
        _wrapper.CopyFile(source, destination);
    }

    private void RenameFileExtensionToPART()
    {
        Console.WriteLine($"Now invoking {nameof(RenameFileExtensionToPART)}");
    }

    public void CopyFiles(IEnumerable<string> source, string destination)
    {
        _wrapper.CopyFiles(source, destination);
    }
}

public class FileLoggingService : IFileService
{
    private IFileService _wrapper;

    public FileLoggingService(IFileService wrapper)
    {
        this._wrapper = wrapper;
    }

    public void CopyFile(string source, string destination)
    {
        Console.WriteLine("Logged Request");
        _wrapper.CopyFile(source, destination);
    }

    public void CopyFiles(IEnumerable<string> source, string destination)
    {
        Console.WriteLine("Logging  requests.");
        _wrapper.CopyFiles(source, destination);
    }
}


class Program
{
    static void Main(string[] args)
    {
        var service = new FileLoggingService(new RenamingFileService(new MainFileService()));
        service.CopyFiles(Enumerable.Range(0,10).Select(x => Guid.NewGuid().ToString()),"Directory");
    }
}

}

0 个答案:

没有答案