implemented chain of responsibility
This commit is contained in:
parent
6c870679a4
commit
1328860453
@ -9,6 +9,7 @@
|
|||||||
- [Structural patterns](#structural-patterns)
|
- [Structural patterns](#structural-patterns)
|
||||||
- [Composition](#composition)
|
- [Composition](#composition)
|
||||||
- [Behavioral patterns](#behavioral-patterns)
|
- [Behavioral patterns](#behavioral-patterns)
|
||||||
|
- [Chain of responsibility](#chain-of-responsibility)
|
||||||
- [Concurrency patterns](#concurrency-patterns)
|
- [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
|
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
|
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.
|
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
|
## Concurrency patterns
|
||||||
Pattenrs for concurrent work and parallel execution in Go.
|
Pattenrs for concurrent work and parallel execution in Go.
|
@ -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
|
||||||
|
}
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user