我一直在努力解决总是使用组合的概念,有很多文章提到几乎所有继承的使用都可以用组合来代替。我知道它有很多好处,比如测试。。。但是,在这种情况下,如何替换继承的使用呢?
基本上我有2个装饰器,它为现有的文件服务类添加了功能。在复制文件之前,我希望它重命名它们,然后委托回原始文件服务。
在这个例子中,我有两种方法。一个循环遍历理论文件列表,然后调用Copy File。decorator类不是复制代码,而是调用包装的实现版本,类似于使用继承。
但是,这并不像继承那样起作用,因为它现在永远不会调用装饰器CopyFrm方法,因为它现在在以前的基类实现中,它不知道装饰器ActhFixFrm方法存在。
如果我使用继承,通过将方法标记为虚拟,基类将知道何时重写了它的一个函数,并调用该版本而不是它自己的版本。
如何仅使用合成来模拟此功能?
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");
}
}
}