jeudi 11 juin 2020

State encapsulation / ability to subscribe to the current state

One of the components in my app needs to subscribe to starred (bookmarked) articles:

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

Article state transitions are managed using 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(); }
}

I want to make Article state property private. But then I need to subscribe to starred articles. I thought about adding a readonly string tag to the ArticleState interface + add getter to the Article:

class StarredArticleState implements ArticleState {
  readonly tag: string = "starred"

...

articles.filter((article: Article) => 
  article.stateTag === "starred"
)

But this neither seems to be a good solution.

How can I solve this?

Aucun commentaire:

Enregistrer un commentaire