18. 状态模式(State)

问题:对象有大量状态判断逻辑(长 switch),状态间转换复杂。

核心:把每个状态封装成独立类,状态切换就是切换当前状态对象。

class Draft {
  constructor(doc) { this.doc = doc; }
  publish() {
    console.log('提交审核');
    this.doc.setState(new Moderation(this.doc));
  }
  reject() { console.log('草稿不能被拒绝'); }
}

class Moderation {
  constructor(doc) { this.doc = doc; }
  publish() {
    console.log('审核通过,已发布');
    this.doc.setState(new Published(this.doc));
  }
  reject() {
    console.log('审核未通过,退回草稿');
    this.doc.setState(new Draft(this.doc));
  }
}

class Published {
  constructor(doc) { this.doc = doc; }
  publish() { console.log('已发布,无需重复操作'); }
  reject() {
    console.log('撤回发布');
    this.doc.setState(new Draft(this.doc));
  }
}

class Document {
  #state;
  constructor() { this.#state = new Draft(this); }
  setState(s) { this.#state = s; }
  publish() { this.#state.publish(); }
  reject() { this.#state.reject(); }
}

const doc = new Document();
doc.publish(); // 提交审核
doc.publish(); // 审核通过,已发布
doc.reject();  // 撤回发布
package state

import "fmt"

type Document struct {
  state State
}

func (d *Document) SetState(s State) { d.state = s }
func (d *Document) Publish()         { d.state.Publish() }
func (d *Document) Reject()          { d.state.Reject() }

type State interface {
  Publish()
  Reject()
}

type Draft struct{ doc *Document }

func (s Draft) Publish() {
  fmt.Println("提交审核")
  s.doc.SetState(Moderation{doc: s.doc})
}

func (s Draft) Reject() { fmt.Println("草稿不能被拒绝") }

type Moderation struct{ doc *Document }

func (s Moderation) Publish() {
  fmt.Println("审核通过,已发布")
  s.doc.SetState(Published{doc: s.doc})
}

func (s Moderation) Reject() {
  fmt.Println("审核未通过,退回草稿")
  s.doc.SetState(Draft{doc: s.doc})
}

type Published struct{ doc *Document }

func (s Published) Publish() { fmt.Println("已发布,无需重复操作") }

func (s Published) Reject() {
  fmt.Println("撤回发布")
  s.doc.SetState(Draft{doc: s.doc})
}