From d1a1cd47252fa8e37c292bd5a8bb3973094cf8ad Mon Sep 17 00:00:00 2001 From: DH Date: Sun, 13 Feb 2022 20:13:51 +0900 Subject: [PATCH] add state, composite pattern --- README.md | 4 +-- behavioral/state.md | 59 +++++++++++++++++++++++++++++++++++ structural/composite.md | 68 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 behavioral/state.md create mode 100644 structural/composite.md diff --git a/README.md b/README.md index 30ebd71..910be1b 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ A curated collection of idiomatic design & application patterns for Go language. | Pattern | Description | Status | |:-------:|:----------- |:------:| | [Bridge](/structural/bridge.md) | Decouples an interface from its implementation so that the two can vary independently | ✘ | -| [Composite](/structural/composite.md) | Encapsulates and provides access to a number of different objects | ✘ | +| [Composite](/structural/composite.md) | Encapsulates and provides access to a number of different objects | ✔ | | [Decorator](/structural/decorator.md) | Adds behavior to an object, statically or dynamically | ✔ | | [Facade](/structural/facade.md) | Uses one type as an API to a number of others | ✘ | | [Flyweight](/structural/flyweight.md) | Reuses existing instances of objects with similar/identical state to minimize resource usage | ✘ | @@ -42,7 +42,7 @@ A curated collection of idiomatic design & application patterns for Go language. | [Memento](/behavioral/memento.md) | Generate an opaque token that can be used to go back to a previous state | ✘ | | [Observer](/behavioral/observer.md) | Provide a callback for notification of events/changes to data | ✔ | | [Registry](/behavioral/registry.md) | Keep track of all subclasses of a given class | ✘ | -| [State](/behavioral/state.md) | Encapsulates varying behavior for the same object based on its internal state | ✘ | +| [State](/behavioral/state.md) | Encapsulates varying behavior for the same object based on its internal state | ✔ | | [Strategy](/behavioral/strategy.md) | Enables an algorithm's behavior to be selected at runtime | ✔ | | [Template](/behavioral/template.md) | Defines a skeleton class which defers some methods to subclasses | ✘ | | [Visitor](/behavioral/visitor.md) | Separates an algorithm from an object on which it operates | ✘ | diff --git a/behavioral/state.md b/behavioral/state.md new file mode 100644 index 0000000..f3c9f55 --- /dev/null +++ b/behavioral/state.md @@ -0,0 +1,59 @@ +# Strategy Pattern +Strategy behavioral design pattern allow an object alter its behavior when its internal state changes. The object will appear on change its class. + +## Implementation +```go +package state +type State interface { + executeState(c *Context) +} + +type Context struct { + StepIndex int + StepName string + Current State +} + +type StartState struct{} + +func (s *StartState) executeState(c *Context) { + c.StepIndex = 1 + c.StepName = "start" + c.Current = &StartState{} +} + +type InprogressState struct{} + +func (s *InprogressState) executeState(c *Context) { + c.StepIndex = 2 + c.StepName = "inprogress" + c.Current = &InprogressState{} +} + +type StopState struct{} + +func (s *StopState) executeState(c *Context) { + c.StepIndex = 3 + c.StepName = "stop" + c.Current = &StopState{} +} +``` + +## Usage + +```go + context := &Context{} + var state State + + state = &StartState{} + state.executeState(context) + fmt.Println("state: ", context) + + state = &InprogressState{} + state.executeState(context) + fmt.Println("state: ", context) + + state = &StopState{} + state.executeState(context) + fmt.Println("state: ", context) +``` \ No newline at end of file diff --git a/structural/composite.md b/structural/composite.md new file mode 100644 index 0000000..19aa197 --- /dev/null +++ b/structural/composite.md @@ -0,0 +1,68 @@ +# Composite Pattern +Composite structural pattern allows composing objects into a tree-like structure and work with the it as if it was a singular object. + +## Interface +```go +package main + +import "fmt" + +type file struct { + name string +} + +func (f *file) search(keyword string) { + fmt.Printf("Searching for keyword %s in file %s\n", keyword, f.name) +} + +func (f *file) getName() string { + return f.name +} +``` + +## Implementation +`search` function will operate applies to both files and folders. For a file, it will just look into the contents of the file; for a folder, it will go through all files of that folder to find that keyword. + +```go +package main + +import "fmt" + +type folder struct { + components []component + name string +} + +func (f *folder) search(keyword string) { + fmt.Printf("Serching recursively for keyword %s in folder %s\n", keyword, f.name) + for _, composite := range f.components { + composite.search(keyword) + } +} + +func (f *folder) add(c component) { + f.components = append(f.components, c) +} +``` + +## Usage +```go +file1 := &file{name: "File1"} +file2 := &file{name: "File2"} +file3 := &file{name: "File3"} + +folder1 := &folder{ + name: "Folder1", +} + +folder1.add(file1) + +folder2 := &folder{ + name: "Folder2", +} +folder2.add(file2) +folder2.add(file3) +folder2.add(folder1) + +folder2.search("rose") +```