oop - 如何理解 DCI 模式

标签 oop design-patterns dci

根据维基百科数据,上下文和交互 (DCI) 是计算机软件中用于对通信对象系统进行编程的范式。这里我不清楚DCI试图解决的问题。你能用简单的例子解释一下吗?您的示例中的数据、上下文和交互是什么?

最佳答案

我理解它的一个简单方法是使用经典的银行应用程序示例。在这个例子中,我将使用 Rails。

假设我们的应用程序有一项功能,用户可以将资金从一个帐户转移到另一个帐户。

我们可能有一个看起来像这样的 Controller :

# app/controllers/accounts_controller.rb
class AccountsController < ApplicationController
  def transfer
    @source_account = Account.find(params[:id])
    @destination_account = Account.find(params[:destination_id])
    @amount = params[:amount]

    if @source_account.transfer_to(@destination_account, @amount)
      flash[:success] = "Successfully transferred #{@amount} to #{@destination_account}"
      redirect_to @source_account
    else
      flash[:error] = "There was a problem transferring money to #{@destination_account}"
      render :transfer
    end
  end
end

在这里,我们调用 transfer_to在我们的其中之一 Account对象。此方法在 Account 中定义模型。
# app/models/account.rb
class Account < ActiveRecord::Base
  def transfer_to(destination_account, amount)
    destination_account.balance += amount
    self.balance -= amount
    save
  end
end

这是一个传统的MVC解决方案——当transfer Controller 上的方法被调用,我们实例化几个模型对象并调用模型上定义的行为。就像罗伯特说的,业务逻辑是分开的,我们必须查看几个不同的地方才能理解代码。

这种方法的缺点是我们最终会在我们的模型中定义很多行为,而这些行为并不总是需要并且缺乏上下文。如果您以前参与过一个大型项目,不久模型文件就会增长到几百甚至几千行代码,因为所有行为都在其中定义。

DCI 可以帮助解决这个问题,方法是让我们的数据模型仅在某些上下文中需要使用该行为。让我们将此应用于我们的银行应用程序示例。

在我们的示例中,上下文正在转移资金。数据将是 Account对象。行为是转移资金的能力。交互是将资金从一个帐户转移到另一个帐户的实际操作。它可能看起来像这样:
# app/contexts/transferring_money.rb
class TransferringMoney # this is our Context
  def initialize(source_account, destination_account) # these objects are our Data
    @source_account = source_account
    @destination_account = destination_account

    assign_roles(source_account)
  end

  def transfer(amount) # here is the Interaction
    @source_account.transfer_to(@destination_account, amount)
  end

  private

  def assign_roles(source_account)
    source_account.extend Transferrer
  end

  module Transferrer
    def transfer_to(destination_account, amount)
      destination_account.balance += amount
      self.balance -= amount
      save
    end
  end
end

从示例中可以看出,当我们调用 source_account.extend Transferrer 时,数据在运行时在上下文中被赋予其行为。 . transfer方法是交互发生的地方。这可以防止我们将逻辑拆分为单独的文件,并且它们都包含在一个 Context 类中。

我们会像这样从 Controller 调用它:
# app/controllers/accounts_controller.rb
class AccountsController < ApplicationController
  def transfer
    @source_account = Account.find(params[:id])
    @destination_account = Account.find(params[:destination_id])
    @amount = params[:amount]

    if TransferringMoney.new(@source_account, @destination_account).transfer(@amount)
      flash[:success] = "Successfully transferred #{@amount} to #{@destination_account}"
      redirect_to @source_account
    else
      flash[:error] = "There was a problem transferring money to #{@destination_account}"
      render :transfer
    end
  end
end

对于这样一个简单的例子,这似乎比它值得的麻烦更多,但是当应用程序变得非常大并且我们向我们的模型添加越来越多的行为时,DCI 变得更加有用,因为我们只在某些情况下向我们的模型添加行为具体互动。这样,模型行为是上下文相关的,我们的 Controller 和模型要小得多。

关于oop - 如何理解 DCI 模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45278269/

相关文章:

oop - 如何从 TypeScript 中的特定子项隐藏父项的方法?

ruby-on-rails - 什么是 DCI,它如何适应 Rails?

javascript - javascript 中的数据上下文交互 (DCI) 和事件编程

excel - 消费/订阅类模块的自定义事件

Python类变量或一般的类变量

c# - 存储库模式与 DTO 模式方法

C++ 设计 : Pool and pointers VS client-server

java - 设计用于插入和删除域对象的数据库接口(interface) API

c - C 中参数数量可变的函数和面向设计的问题

design-patterns - DCI - 数据、上下文和交互 - MVC 的继承者?