Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add some pattern example #112

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ A curated collection of idiomatic design & application patterns for Go language.

| Pattern | Description | Status |
|:-------:|:----------- |:------:|
| [Abstract Factory](/creational/abstract_factory.md) | Provides an interface for creating families of releated objects | |
| [Abstract Factory](/creational/abstract_factory.md) | Provides an interface for creating families of releated objects | |
| [Builder](/creational/builder.md) | Builds a complex object using simple objects | ✔ |
| [Factory Method](/creational/factory.md) | Defers instantiation of an object to a specialized function for creating instances | ✔ |
| [Object Pool](/creational/object-pool.md) | Instantiates and maintains a group of objects instances of the same type | ✔ |
Expand All @@ -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 | ✘ |
Expand All @@ -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 | ✘ |
Expand Down
59 changes: 59 additions & 0 deletions behavioral/state.md
Original file line number Diff line number Diff line change
@@ -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)
```
55 changes: 55 additions & 0 deletions creational/abstract_factory.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Abstract Factory Method Pattern

Abstract Factory method creational design pattern allows providing interface that creating objects without having to specify the exact type of the object that will be created.

## Implementation

The example implementation shows how to make a phone from different copmanies.

### Types

```go
package company

type iCompnayFactory interface {
makePhone() iPhone
}
```

### Different Implementations

```go
package company

type CompnayType int

const (
SAMSNUG CompnayType = iota
APPLE
)

func getCompnayFactory(compnay CompnayType) (iCompnayFactory, error) {
switch compnay {
case SAMSNUG:
return &samsungFactory{}, nil
case APPLE:
return &appleFactory{}, nil
default:
return nil, fmt.Errorf(/* .. */)
}
}
```

## Usage

With the abstract factory method, the user can provide an interface for creating families of releated objects.

```go
appleFactory, _ := getCompnayFactory(APPLE)
applePhone := appleFactory.makePhone();
applePhone.makeCall(/*...*/);

samsungFactory, _ := getCompnayFactory(SAMSNUG)
samsungPhone := samsungFactory.makePhone();
samsungPhone.makeCall(/*...*/);
```
68 changes: 68 additions & 0 deletions structural/composite.md
Original file line number Diff line number Diff line change
@@ -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")
```