代码之家  ›  专栏  ›  技术社区  ›  Ambidex

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

  •  0
  • Ambidex  · 技术社区  · 7 年前

    我一直在努力解决总是使用组合的概念,有很多文章提到几乎所有继承的使用都可以用组合来代替。我知道它有很多好处,比如测试。。。但是,在这种情况下,如何替换继承的使用呢?

    基本上我有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");
        }
    }
    

    }

    0 回复  |  直到 7 年前