【问题标题】:Composite design pattern: how to pass results from one component into another?复合设计模式:如何将结果从一个组件传递到另一个组件?
【发布时间】:2017-09-28 13:48:19
【问题描述】:

我有以下代码:

interface IService
{
    void Execute();
}

class ServiceA : IService
{
    public void Execute() { ... }
}

class ServiceB : IService
{
    public void Execute() { ... }
}

class ServiceComposite : IService
{
    List<IService> _services = new List<IService>();

    public ServiceComposite()
    {
        _services.Add(new ServiceA());
        _services.Add(new ServiceB());
    }

    public void Execute()
    {
        foreach (IService service in _services)
        {
            service.Execute();
        }
    }
}

问题在于ServiceB 依赖于ServiceA 的一些结果。我的想法是创建容器类来存储结果,然后将其注入到 ServiceA 和 ServiceB 中:

class ServiceResults
{
    public string SomeProperty {get; set;}
}

public ServiceComposite()
{
    ServiceResults result = new ServiceResults();
    _services.Add(new ServiceA(result));
    _services.Add(new ServiceB(result));
}

我想知道这是否是解决问题的最佳方法。也许它违反了一些我不知道的原则或规则,或者只是“代码味道”。有什么更好的方法来做到这一点?

【问题讨论】:

  • 我很想知道为什么 B 需要来自 A 的结果 - 如果是这样的话,将它们视为两个单独的实现似乎是不正确的。
  • 或者服务 A 可以将结果作为属性公开,并将服务 A 作为服务 B 的依赖项传递
  • 您实际上也没有在这里实现“复合”模式。
  • @Servy,你为什么这么说?
  • @jaco0646 一个实例组成两个特定的其他实现不同于一般地组成任意数量的任何类型的对象,包括那些本身可以与其他对象组合的对象,这些对象本身可以与其他对象组合对象等。复合模式是树的表示,这不能表示任何树。

标签: c# design-patterns composite design-principles


【解决方案1】:

如果ServiceB 需要ServiceA 的结果才能正常运行,那么为什么不使用ServiceB 取决于ServiceA

public interface IService 
{
    void Execute();
}

public class ServiceA : IService
{
    public void Execute() { ... }
}

class ServiceB : IService
{
    public ServiceB(IService service)
    {
        Service = service;
    }

    public void Execute() { ... }

    public IService Servie { get; set; }
}

然后,如果您执行集合中的所有Services,您可以添加ServiceBase 以确保此服务仅执行一次:(完整示例)

在这个基本实现上,您可以添加:异步ExecuteInnerExecute 执行的线程安全检查、用于生成特定IService 的享元工厂、具有派生的ResponseBase每个Service....的响应

public class ServiceResponse { }
public interface IService
{
    ServiceResponse Execute();
}

public abstract class ServiceBase : IService
{
    public ServiceResponse Execute()
    {
        if (_response == null)
        {
            _response = InnerExecute();
        }
        return _response;
    }

    public abstract ServiceResponse InnerExecute();

    private ServiceResponse _response;
}

public class ServiceA : ServiceBase
{
    public override ServiceResponse InnerExecute()
    {
        return new ServiceResponse();
    }
}

public class ServiceB : ServiceBase
{
    public ServiceB(IServiceFactory serviceFactory)
    {
        ServiceFactory= serviceFactory;
    }

    public override ServiceResponse InnerExecute()
    {
        return ServiceFactory.GetServices(ServicesTypes.ServiceA).Execute();
    }

    public IServiceFactory ServiceFactory { get; set; }
}

以及使用这些Services 的人:

public enum ServicesTypes 
{
    ServiceA,
    ServiceB....
}

public interface IServiceFactory
{
    IEnumerable<IService> GetServices();

    IService GetServices(ServicesTypes servicesTypes);
}

public class SomeOtherThatExecuteServices
{
    public SomeOtherThatExecuteServices(IServiceFactory serviceFactory)
    {
        ServiceFactory = serviceFactory;
    }

    public IEnumerable<ServiceResponse> ExecuteServices()
    {
        return ServiceFactory.GetServices()
                             .Select(service => service.Execute());
    }

    public IServiceFactory ServiceFactory { get; set; }
}

您可能希望通过某个映射键访问工厂,并且您可能希望在 SomeOtherThatExecuteServices 中使用正确的逻辑,但这一切都会让您走上正确的道路(+使用一些适当的 IoC 容器) em>

【讨论】:

    猜你喜欢
    • 2018-11-10
    • 1970-01-01
    • 2020-12-30
    • 1970-01-01
    • 2023-01-30
    • 2021-10-31
    • 2019-11-06
    相关资源
    最近更新 更多