2
\$\begingroup\$

The Article model supports a bunch of transitions. Only two are shown below: star()/unstar().

Is this a valid implementation of the state pattern?

interface ArticleState {
  star(): ArticleState;
  unstar(): ArticleState;
  // other transitions ...
}

export class InitialArticleState implements ArticleState {
  star   = () => new StarredArticleState();
  unstar = () => this;
  // other transitions ...
}

export class StarredArticleState implements ArticleState {
  star   = () => this;
  unstar = () => new InitialArticleState();
  // other transitions ...
}

export class Article {  
  state: ArticleState = new InitialArticleState();  
  star() { this.state = this.state.star(); }
  unstar() { this.state = this.state.unstar(); }
}

The Article state operations are wrapped by the service which updates the feed:

@Injectable()
export class ArticlesFeedService {

  private feed$: Subject<Article[]> = new BehaviorSubject<Article[]>([]);
  private store: Article[] = [];

  private publishChanges() {
    this.feed$.next(this.store);
  }

  starArticle(article: Article): void {
    article.star();
    // update the store then publish changes...
  }
}

There's a component subscribed to get starred articles:

getStarredArticles(): Observable<Article[]> {
  return this.getArticles().pipe(
    map((articles: Article[]) => 
      articles.filter((article: Article) => 
        article.state instanceof StarredArticleState
      )
    )
  );
}

My motivation behind using the state pattern is that it helps reduce branching (decision making) in the feed service methods (e.g. starred article can't be blacklisted, only unstarred / initial).

  1. Is it okay to use state as public property of the Article? I thought about marking the article's state property as private and introducing a readonly string tag to each state (to ArticleState interface), so I could subscribe/filter using the tag. But it's a string and I'm tottally not sure if it's better.
  2. How can I improve the design?
  3. Are there any TypeScript features that could be used instead?
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Welcome to Code Review! I changed the title so that it describes what the code does per site goals: "State what your code does in your title, not your main concerns about it.". Feel free to edit and give it a different title if there is something more appropriate. \$\endgroup\$ Jun 10, 2020 at 17:47
  • \$\begingroup\$ @SᴀᴍOnᴇᴌᴀ thanks! Well, I tried to be more descriptive, updated the title. \$\endgroup\$
    – lexeme
    Jun 11, 2020 at 7:39

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.