github.com/kaydxh/golang@v0.0.131/tutorial/programming_paradigm/control.inverse_test.go (about)

     1  package tutorial
     2  
     3  import (
     4  	"errors"
     5  	"testing"
     6  )
     7  
     8  // Undo 是控制逻辑,与业务逻辑分开,业务逻辑依赖控制逻辑Undo,而不是控制
     9  // 逻辑依赖业务逻辑
    10  type Undo []func()
    11  
    12  func (undo *Undo) Add(function func()) {
    13  	*undo = append(*undo, function)
    14  }
    15  
    16  func (undo *Undo) Undo() error {
    17  	functions := *undo
    18  	if len(functions) == 0 {
    19  		return errors.New("No functions to undo")
    20  	}
    21  	index := len(functions) - 1
    22  	if function := functions[index]; function != nil {
    23  		function()
    24  		functions[index] = nil // For garbage collection
    25  	}
    26  	*undo = functions[:index]
    27  	return nil
    28  }
    29  
    30  type IntSet struct {
    31  	data map[int]bool
    32  	undo Undo
    33  }
    34  
    35  func NewIntSet() IntSet {
    36  	return IntSet{data: make(map[int]bool)}
    37  }
    38  
    39  func (set *IntSet) Undo() error {
    40  	return set.undo.Undo()
    41  }
    42  
    43  func (set *IntSet) Contains(x int) bool {
    44  	return set.data[x]
    45  }
    46  
    47  func (set *IntSet) Add(x int) {
    48  	if !set.Contains(x) {
    49  		set.data[x] = true
    50  		set.undo.Add(func() { set.Delete(x) })
    51  	} else {
    52  		set.undo.Add(nil)
    53  	}
    54  }
    55  
    56  func (set *IntSet) Delete(x int) {
    57  	if set.Contains(x) {
    58  		delete(set.data, x)
    59  		set.undo.Add(func() { set.Add(x) })
    60  	} else {
    61  		set.undo.Add(nil)
    62  	}
    63  }
    64  
    65  func TestUndo(t *testing.T) {
    66  	s := NewIntSet()
    67  	s.Add(10)
    68  	s.Add(5)
    69  	t.Logf("s: %v", s)
    70  	s.Undo()
    71  	t.Logf("s: %v", s)
    72  }