package main
import (
"errors"
"fmt"
)
type Widget struct {
X, Y int
}
type Label struct {
Widget // Embedding (delegation)
Text string // Aggregation
}
func (label Label) Paint() {
fmt.Printf("%p:Label.Paint(%q)\n", &label, label.Text)
}
type Button struct {
Label
}
// Embedding (delegation)}
type ListBox struct {
Widget // Embedding (delegation)
Texts []string //Aggregation
Index int //Aggregation
}
// 因为这个接口可以通过 Label 的嵌入带到新的结构体,
// 所以,可以在 Button 中重载这个接口方法
func (button Button) Paint() { // Override
fmt.Printf("Button.Paint(%s)\n", button.Text)
}
func (button Button) Click() {
fmt.Printf("Button.Click(%s)\n", button.Text)
}
func (listBox ListBox) Paint() {
fmt.Printf("ListBox.Paint(%q)\n", listBox.Texts)
}
func (listBox ListBox) Click() {
fmt.Printf("ListBox.Click(%q)\n", listBox.Texts)
}
type Painter interface {
Paint()
}
type Clicker interface {
Click()
}
func main() {
label := Label{
Widget: Widget{
X: 1,
Y: 2,
},
Text: "88888888899999",
}
label.Paint()
button := Button{
Label: label,
}
button.Paint()
button1 := Button{
Label{
Widget{10, 70},
"OK",
},
}
button2 := Button{
Label{
Widget{50, 70},
"Cancel",
},
}
listBox := ListBox{
Widget{10, 40},
[]string{"AL", "AK", "AZ", "AR"},
0,
}
for _, painter := range []Painter{label, listBox, button1, button2} {
painter.Paint()
}
for _, widget := range []interface{}{label, listBox, button1, button2} {
widget.(Painter).Paint()
if clicker, ok := widget.(Clicker); ok {
clicker.Click()
}
fmt.Println() // print a empty line
}
}
type IntSet struct {
data map[int]bool
}
func NewIntSet() IntSet {
return IntSet{make(map[int]bool)}
}
func (set *IntSet) Add(x int) {
set.data[x] = true
}
func (set *IntSet) Delete(x int) {
delete(set.data, x)
}
func (set *IntSet) Contains(x int) bool {
return set.data[x]
}
type UndoableIntSet struct { // Poor style
IntSet // Embedding (delegation)
functions []func()
}
type IntSetV2 struct {
data map[int]bool
undo Undo
}
func NewUndoableIntSet() UndoableIntSet {
return UndoableIntSet{NewIntSet(), nil}
}
func NewIntSetV2() IntSetV2 {
return IntSetV2{data: make(map[int]bool)}
}
func (set *UndoableIntSet) Add(x int) { // Override
if !set.Contains(x) {
set.data[x] = true
set.functions = append(set.functions, func() { set.Delete(x) })
} else {
set.functions = append(set.functions, nil)
}
}
// 控制反转
func (set *IntSetV2) Add(x int) {
if !set.Contains(x) {
set.data[x] = true
set.undo.Add(func() { set.Delete(x) })
} else {
set.undo.Add(nil)
}
}
func (set *UndoableIntSet) Delete(x int) { // Override
if set.Contains(x) {
delete(set.data, x)
set.functions = append(set.functions, func() { set.Add(x) })
} else {
set.functions = append(set.functions, nil)
}
}
// 控制反转
func (set *IntSetV2) Delete(x int) {
if set.Contains(x) {
delete(set.data, x)
set.undo.Add(func() { set.Add(x) })
} else {
set.undo.Add(nil)
}
}
// 控制反转
func (set *IntSetV2) Contains(x int) bool {
return set.data[x]
}
// 控制依赖业务
func (set *UndoableIntSet) Undo() error {
if len(set.functions) == 0 {
return errors.New("No functions to undo")
}
index := len(set.functions) - 1
if function := set.functions[index]; function != nil {
function()
set.functions[index] = nil // For garbage collection
}
set.functions = set.functions[:index]
return nil
}
// 控制和业务解耦
// 控制反转-----------业务逻辑依赖控制,实现代码复用;
func (set *IntSetV2) Undo() error {
return set.undo.Undo()
}
// 反转依赖
type Undo []func()
// 控制逻辑---业务依赖控制逻辑
func (undo *Undo) Add(function func()) {
*undo = append(*undo, function)
}
// 业务依赖控制,undo没有和业务相关的依赖
func (undo *Undo) Undo() error {
functions := *undo
if len(functions) == 0 {
return errors.New("No functions to undo")
}
index := len(functions) - 1
if function := functions[index]; function != nil {
function()
functions[index] = nil // For garbage collection
}
*undo = functions[:index]
return nil
}