【问题标题】:Design pattern for translating multiple data-formats from multiple sources to a single format将多种数据格式从多个来源转换为单一格式的设计模式
【发布时间】:2015-08-07 13:19:23
【问题描述】:

我在一家拥有多个网站的公司工作,而现有的基础设施……嗯,很糟糕。

现在,每家商店都有自己的桌子,桌子的结构各不相同。这正在迅速成为一个问题(如果还没有的话)。

所以我需要找到一种方法从多个渠道接受订单,将它们格式化为单一、统一的方式,将它们存储在我们端,并将它们转换回商店 API 期望的格式(可以是从RESTful JSON 到 SOAP)。

我最初的直觉反应是混合了工厂、访问者和构建器模式(加上一些智能多态性),但它变得有点太复杂太快了。在我将自己编码到一个可能不是最优、可维护或可扩展的解决方案的角落之前,是否有一种或一组模式会更有效?

基本上,我认为它会是这样的:

Source -> Translator -> Our Format
Our Format -> Translator -> Source

我不需要翻译器对数据进行实际操作。它应该负责的只是以正确的格式获取它,我们可以从 A 点到 B 点获取它(反之亦然)。

关于系统的一些假设:

  1. 我们这边的格式不太可能改变,因此我们的对象也不太可能改变
  2. 当数据转换回原始源时,我们可以假设所需的一切都在那里。出站请求的实际行为很小、重点突出且定义明确

【问题讨论】:

    标签: oop design-patterns ooad


    【解决方案1】:

    Adapter Pattern 是你的朋友。假设您有一个旧版 Customer 类。

    public class CustomerLegacy
    {
        public string FirstName { get; set; }
    
        public string LastName { get; set; }
    
        public DateTime Birthday { get; set; }
    }
    

    您可能想要做的第一件事是提取该类。此步骤是可选的,但它使新类可测试。因此,您将拥有如下所示的 ICustomerLegacy 界面。

    public interface ICustomerLegacy
    {
        string FirstName { get; set; }
    
        string LastName { get; set; }
    
        DateTime Birthday { get; set; }
    }
    

    然后重构CustomerLegacy类来实现新的接口。

    public class CustomerLegacy
        : ICustomerLegacy
    

    下一步是创建一个将ICustomerLegacy 作为构造函数参数的适配器。您可以添加新属性以满足您的需求。

    public class CustomerAdapter
    {
        private readonly ICustomerLegacy customer;
    
        public CustomerAdapter(ICustomerLegacy customer)
        {
            this.customer = customer;
        }
    
        public string FullName
        {
            get
            {
                return this.customer.FirstName + " " + this.customer.LastName;
            }
        }
    
        public int Age
        {
            get
            {
                return DateTime.UtcNow.Year - this.customer.Birthday.Year;
            }
            set
            {
                // your logic here.
            }
        }
    
        public void Save()
        {
            //this.customer.DoSomething();
        }
    }
    

    如您所见,适配器模式可以帮助您重构现有产品,使其可测试,并在一处整理遗留代码。

    【讨论】:

      【解决方案2】:

      据我所知,您应该能够使用一种简单的方法来处理这种情况,使用工厂和接口,

      class IStore
      {
         void Place(Order order);
      
         ....other methods
      }
      
      class AmazonStore : IStore
      {
         ...implement methods
      }
      
      class EbayStore : IStore
      {
          ...implement methods
      }
      

      这里的 Order 对象应该被转换为实际实现中的特定 API,并且对于任何获取数据的方法也应该反过来。

      然后可以使用工厂基于常量或基于枚举创建相关存储。

      【讨论】:

        【解决方案3】:

        在我以前的一家公司,我们从事过类似的项目。我们采用Pipe and filters 架构。

        使用管道和过滤器架构风格将较大的处理任务划分为一系列较小的独立处理步骤(过滤器),这些步骤由通道(管道)连接。

        每个过滤器都公开了一个非常简单的接口:它在入站管道上接收消息,处理消息,并将结果发布到出站管道。管道将一个过滤器连接到下一个过滤器,将输出消息从一个过滤器发送到下一个过滤器。因为所有组件都使用相同的外部接口,所以它们可以通过将组件连接到不同的管道来组合成不同的解决方案。我们可以添加新的过滤器、省略现有的过滤器或将它们重新排列成新的序列——所有这些都无需更改过滤器本身。过滤器和管道之间的连接有时称为端口。在基本形式中,每个过滤器组件都有一个输入端口和一个输出端口。

        把它想象成你的Source 是泵,你的Translator 是过滤器。过滤器中的任何功能都将从相应的业务领域驱动。大图是这样的:

        【讨论】:

          猜你喜欢
          • 2016-10-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-02-28
          • 2018-01-20
          • 2023-03-19
          • 2014-08-24
          • 1970-01-01
          相关资源
          最近更新 更多