首页 > 解决方案 > 广泛使用工厂构造函数是个好主意吗?

问题描述

我的问题是关于在处理相对复杂的不可变对象时如何正确使用工厂构造函数。假设我想返回一个更改了某些属性的类的实例。

例子

@immutable
class SomeObject {
  final int id;
  final String name;
  final int upvote;
  final int downvote;
  final int favorite;

  SomeObject({this.id, this.name, this.upvote, this.downvote, this.favorite});

  factory SomeObject.upvoted() {
    return SomeObject(
      upvote: this.upvote + 1 // apparently can't use this keyword here, wrong syntax
    );
  }
  SomeObject.upvoted(SomeObject ref) {
    id = ref.id;
    // cant change an immutable type
  }

  SomeObject upvoted() {
    return SomeObject(
      upvote: upvote + 1,
      //... other properties are null, bad idea?
    );
  }

  SomeObject upvotedWithDefaultConstructorUsingReference(SomeObject ref) {
    // works but seems like an overkill, especially considering more number of properties
    return SomeObject(
      id: ref.id,
      name: ref.name,
      upvote: upvote + 1,
      downvote: ref.downvote,
      favorite: ref.downvote
    );
  }
}

SomeObject.upvoted() 将是同一类的一个实例,但它的 upvoted 属性比引用的属性多 +1。还会有更多类似 downvoted()、withNameChanged() 或 copyWith()。

前两个是构造函数,其他只是返回 SomeObject 类实例的方法。这里应该采用什么方法?当类不可变时如何使用工厂构造函数?我也不确定这 4 个例子的区别。

我已经阅读了这个问题的答案,但似乎没有回答我的问题。

标签: oopflutterdartconstructor

解决方案


看起来你想要一个copyWith类型模式:

class SomeObject {
  final int id;
  final String name;
  final int upVote;
  final int downVote;
  final int favorite;

  SomeObject({this.id, this.name, this.upVote, this.downVote, this.favorite});

  SomeObject copyWith({
    int id,
    String name,
    int upVote,
    int downVote,
    int favorite,
  }) {
    return SomeObject(
      id: id ?? this.id,
      name: name ?? this.name,
      upVote: upVote ?? this.upVote,
      downVote: downVote ?? this.downVote,
      favorite: favorite ?? this.favorite,
    );
  }
}

你可以用任何你喜欢的方式来调整它:递增的upVoted副本,upVote其余的保持不变,或者允许它们被改变。

  SomeObject upVoted() {
    return SomeObject(
      id: id, // no need for 'this' here
      name: name,
      upVote: upVote + 1,
      downVote: downVote,
      favorite: favorite,
    );
  }

将两者结合起来,您可以想出无穷无尽的变化:

  SomeObject upVoted() => copyWith(upVote: upVote + 1);
  SomeObject downVoted() => copyWith(downVote: downVote + 1);
  SomeObject upVoteRetracted() => copyWith(upVote: upVote - 1);

...这让你开始怀疑为什么这个类是不可变的。让它保持和改变它的状态似乎更有意义,而不是制作具有不同值的多个副本。


推荐阅读