如何处理构造函数中的参数太多的类-Scala?

时间:2018-11-05 15:22:58

标签: scala class inheritance constructor builder

我正在对本质上具有许多字段的某些数据类型进行建模。

然后,我得到的是丑陋的代码,其中该类的构造函数具有一长列参数及其所有子类。

我有点怀疑 BuilderPattern 是否是一个好的解决方案。

例如,这是通用类Transaction

class Transaction(
    source: String,
    format: String,
    id: String,
    amount: Double,
    currency: String,
    senderAccount: String,
    senderName: String,
    receiverAccount: String,
    receiverName: String,
    execDate: LocalSate,
    createdDateTime: Instant)

这是子类A TxTypeA,它具有一些特定于typeA的特殊字段:

class TxTypeA(
    source: String,
    format: String,
    id: String,
    amount: Double,
    currency: String,
    senderAccount: String,
    senderName: String,
    receiverAccount: String,
    receiverName: String,
    execDate: LocalSate,
    createdDateTime: Instant,
    typeAField1: String,
    typeAField2: String,
    typeAField3: String
) extends Transaction(
    source,
    format,
    id,
    amount,
    currency,
    senderAccount,
    senderName,
    receiverAccount,
    receiverName,
    execDate,
    createdDateTime)

这是子类B TxTypeB,它具有一些特定于typeB的特殊字段:

class TxTypeB(
    source: String,
    format: String,
    id: String,
    amount: Double,
    currency: String,
    senderAccount: String,
    senderName: String,
    receiverAccount: String,
    receiverName: String,
    execDate: LocalSate,
    createdDateTime: Instant,
    typeBField1: String,
    typeBField2: String,
    typeBField3: String,
    typeBField4: String,
    typeBField5: String,
    typeBField6: String,
    typeBField7: String
) extends Transaction(
    source,
    format,
    id,
    amount,
    currency,
    senderAccount,
    senderName,
    receiverAccount,
    receiverName,
    execDate,
    createdDateTime)

有人对此有更好的解决方案吗?

更新:

在我的项目中,我创建了另一个名为Party的类,该类包装了AccountName,但这只是释放了痛苦,并未解决核心问题。 / p>

case class Party(account: String, name: String)

class Transaction(
    source: String,
    format: String,
    id: String,
    amount: Double,
    currency: String,
    senderParty: Party,
    receiverParty: Party,
    execDate: LocalSate,
    createdDateTime: Instant)

3 个答案:

答案 0 :(得分:1)

您可以通过使Transaction为特征来对此进行整理:

trait Transaction {
  val source: String
  val format: String
  val id: String
  val amount: Double
  val currency: String
  val senderAccount: String
  val senderName: String
  val receiverAccount: String
  val receiverName: String
  val execDate: LocalState
  val createdDateTime: Instant
}

case class TxTypeA(
  source: String,
  format: String,
  id: String,
  amount: Double,
  currency: String,
  senderAccount: String,
  senderName: String,
  receiverAccount: String,
  receiverName: String,
  execDate: LocalState,
  createdDateTime: Instant,
  typeAField1: String,
  typeAField2: String,
  typeAField3: String
) extends Transaction

case class TxTypeB(
  source: String,
  format: String,
  id: String,
  amount: Double,
  currency: String,
  senderAccount: String,
  senderName: String,
  receiverAccount: String,
  receiverName: String,
  execDate: LocalState,
  createdDateTime: Instant,
  typeBField1: String,
  typeBField2: String,
  typeBField3: String,
  typeBField4: String,
  typeBField5: String,
  typeBField6: String,
  typeBField7: String
) extends Transaction

如果需要,您甚至可以将这些值组合成包含相关字段的小写类,如下所示:

case class Party(account: String, name: String)

trait Transaction {
  val source: String
  val format: String
  val id: String
  val amount: Double
  val currency: String
  val sender: Party
  val receiver: Party
  val execDate: LocalState
  val createdDateTime: Instant
}

case class TxTypeA(
  source: String,
  format: String,
  id: String,
  amount: Double,
  currency: String,
  sender: Party,
  receiver: Party,
  execDate: LocalState,
  createdDateTime: Instant,
  typeAField1: String,
  typeAField2: String,
  typeAField3: String
) extends Transaction

case class TxTypeB(
  source: String,
  format: String,
  id: String,
  amount: Double,
  currency: String,
  sender: Party,
  receiver: Party,
  execDate: LocalState,
  createdDateTime: Instant,
  typeBField1: String,
  typeBField2: String,
  typeBField3: String,
  typeBField4: String,
  typeBField5: String,
  typeBField6: String,
  typeBField7: String
) extends Transaction

或者您可以走得更远,将Transaction作为参数传递而不是扩展它:

case class Party(account: String, name: String)

case class Transaction (
  val source: String,
  val format: String,
  val id: String,
  val amount: Double,
  val currency: String,
  val sender: Party,
  val receiver: Party,
  val execDate: LocalState,
  val createdDateTime: Instant
)

case class TxTypeA(
  transaction: Transaction,
  typeAField1: String,
  typeAField2: String,
  typeAField3: String
)

case class TxTypeB(
  transaction: Transaction,
  typeBField1: String,
  typeBField2: String,
  typeBField3: String,
  typeBField4: String,
  typeBField5: String,
  typeBField6: String,
  typeBField7: String
)

这取决于您的用例以及可行的方法。如果您正在执行格式化Json的操作,我建议您对其进行扩展,以使Json字段匹配(或创建特定的Reads等)。

答案 1 :(得分:0)

为什么不使用案例类来建模相关信息?例如交易中的发送者和接收者可以建模为单独的案例类;

case class Account(id: String, name: String)


class Transaction(
    source: String,
    format: String,
    id: String,
    amount: Double,
    currency: String,
    sender: Account
    reciever: Account
    execDate: LocalSate,
    createdDateTime: Instant)

这样,您可以减少构造函数中的参数数量。然后,您可以将辅助方法添加到Transaction类或实现构建器模式,例如TransactionBuilder.withSender(senderName,senderAccountId)

答案 2 :(得分:0)

在这种情况下,我希望将这些字段组合到其他类中。

例如,交易可以由发送者,接收者,金额等组成。