Является ли хорошей идеей широко использовать конструкторы Factory? - PullRequest
1 голос
/ 17 апреля 2020

Мой вопрос о том, как правильно использовать конструкторы Factory при работе с относительно полными неизменяемыми объектами. Предположим, я хочу вернуть экземпляр класса с некоторыми измененными свойствами.

Пример

@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 () будет экземпляром тот же класс, но его свойство с присвоенным голосом на +1 больше, чем указанный. И будет больше похоже на downvoted (), withNameChanged () или copyWith ().

Первые 2 - это конструкторы, а другие - просто методы, которые возвращают экземпляр класса SomeObject. Какой здесь должен быть подход? Как я могу использовать фабричные конструкторы, когда класс неизменен? Также я не уверен в разнице этих 4 примеров.

Я уже прочитал ответы на этот вопрос, но, похоже, он не отвечает на мой.

1 Ответ

1 голос
/ 17 апреля 2020

Похоже, вам нужен шаблон типа 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);

... что тогда заставляет задуматься, почему этот класс неизменен , Кажется, что было бы более разумно держать его и изменять его состояние, а не делать несколько копий с разными значениями.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...