implemented chain of responsibility

This commit is contained in:
ismayilmalik 2018-01-01 21:29:51 +03:00
parent 6c870679a4
commit 1328860453
3 changed files with 122 additions and 0 deletions

View File

@ -9,6 +9,7 @@
- [Structural patterns](#structural-patterns)
- [Composition](#composition)
- [Behavioral patterns](#behavioral-patterns)
- [Chain of responsibility](#chain-of-responsibility)
- [Concurrency patterns](#concurrency-patterns)
---
@ -39,6 +40,10 @@ between objects. Behavio ral patterns describe not just patterns of objects or c
but also the patterns of communication between them. These patterns characterize
complex control flow that's difficult to follow at run-time. They shift your focus away
from flow of control to let you concent ratejust on the way objects are interconnected.
### Chain of responsibility
Avoid coupling the sender of a request to its receiver by giving more than one
object a chance to handle the request. Chain the receiving objects and pass the
request along the chain until an object handles it.
## Concurrency patterns
Pattenrs for concurrent work and parallel execution in Go.

View File

@ -0,0 +1,81 @@
package chain_of_responsibility
import (
"errors"
"fmt"
"encoding/json"
)
type Handler interface {
Handle(interface{}) error
}
type Book struct {
Title string
Author string
}
func (b Book) String() string {
return fmt.Sprintf("%b", b)
}
type Deserializer struct {
next Handler
}
func (h *Deserializer) Handle(data interface{}) error {
var book Book
bytes, ok := data.([]byte)
if !ok {
return errors.New("Unsupported type!")
}
if err := json.Unmarshal(bytes, &book); err != nil {
return err
}
if h.next != nil {
return h.next.Handle(book)
}
return nil
}
type Logger struct {
next Handler
}
func (h *Logger) Handle(data interface{}) error {
book, ok := data.(Book)
if !ok {
return errors.New("Argument is not a Book instance")
}
fmt.Println("Book received! Titlle: '%s' Author: '%s", book.Title, book.Author)
if h.next != nil {
return h.next.Handle(book)
}
return nil
}
type BookDb struct {
store map[string]Book
next Handler
}
func (h *BookDb) Handle(data interface{}) error {
book, ok := data.(Book)
if !ok {
return errors.New("Argument is not a Book instance")
}
h.store[book.Title]=book
if h.next != nil {
return h.next.Handle(book)
}
return nil
}

View File

@ -0,0 +1,36 @@
package chain_of_responsibility
import (
"encoding/json"
"testing"
)
func TestCORPattern(t *testing.T) {
book := Book{"Go design patterns", "Ismayil Malik"}
bytes, _ := json.Marshal(book)
bookDb := &BookDb{
make(map[string]Book),
nil,
}
logger := &Logger{
next: bookDb,
}
chain := &Deserializer{
next: logger,
}
t.Run(`It will be unmurshalled on deserializer handler then will be logged
on logger handler and at the end will be presisted by third handler`, func(t *testing.T) {
err := chain.Handle(bytes)
if err != nil {
t.Fatalf("Something went wrong: %s", err.Error())
}
storedBook := bookDb.store[book.Title]
if storedBook != book {
t.Errorf("Expected %b but got %b", book, storedBook)
}
})
}