mirror of
https://github.com/tmrts/go-patterns.git
synced 2024-11-25 14:36:06 +03:00
Realisation of behavioral-mediator pattern
This commit is contained in:
parent
f978e42036
commit
3bb0d5199d
@ -38,7 +38,7 @@ A curated collection of idiomatic design & application patterns for Go language.
|
||||
|:-------:|:----------- |:------:|
|
||||
| [Chain of Responsibility](/behavioral/chain_of_responsibility.md) | Avoids coupling a sender to receiver by giving more than object a chance to handle the request | ✘ |
|
||||
| [Command](/behavioral/command.md) | Bundles a command and arguments to call later | ✘ |
|
||||
| [Mediator](/behavioral/mediator.md) | Connects objects and acts as a proxy | ✘ |
|
||||
| [Mediator](/behavioral/mediator.md) | Connects objects and acts as a proxy | ✔ |
|
||||
| [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 | ✘ |
|
||||
|
43
behavioral/mediator.md
Normal file
43
behavioral/mediator.md
Normal file
@ -0,0 +1,43 @@
|
||||
# Mediator Pattern
|
||||
The [mediator pattern](https://en.wikipedia.org/wiki/Mediator_pattern) allows to objects no longer communicate directly with each other, but instead communicate through the mediator. This reduces the dependencies between communicating objects, thereby reducing coupling. In plain words, your object(s) must know about "mediator" to communicate with another object across a "mediator". So, that allows to "mediator" implements cooperative behavior by sending a request to one or more.
|
||||
|
||||
## Implementation
|
||||
To implement you will need:
|
||||
- ``Mediator interface`` - an intermediary describing the organization of the process of information exchange between objects
|
||||
- ``The Concrete Mediator``, which implements the Mediator interface
|
||||
- ``Colleague interface`` - describing the organization of the process of interaction of collaborative objects with an object of the Mediator type
|
||||
- ``The Concrete Colleague`` that implements the Colleague interface. Each object-colleague knows only about the object-mediator. All objects-colleagues exchange information only through an intermediary.
|
||||
|
||||
## Usage
|
||||
### Mediator interface and Concrete Mediator to communicate between objects
|
||||
```go
|
||||
type Mediator interface {
|
||||
AddCollegue(c Colleague)
|
||||
Communicate(c Colleague)
|
||||
}
|
||||
|
||||
type ConcreteMediator struct {
|
||||
Colleague *list.List
|
||||
}
|
||||
```
|
||||
|
||||
### Colleague interface and Concrete Colleague, all communications must be possible through ``mediator.Communicate()`` in ``ConcreteColleague``
|
||||
```go
|
||||
type Colleague interface {
|
||||
GetData() interface{}
|
||||
}
|
||||
|
||||
type ConcreteColleague struct {
|
||||
mediator ConcreteMediator
|
||||
}
|
||||
```
|
||||
|
||||
For better explanation watch short code of chat room example: ([on playground](https://play.golang.org/p/lsBkEEfkCv)) or see local example [mediator/main.go](mediator/main.go)
|
||||
|
||||
## Rules of Thumb
|
||||
GoF design patterns recommends use when:
|
||||
- A set of objects communicate in well-defined but a complex way. So resulting are unstructured and complex to understand.
|
||||
- Reusing an object is difficult because it refers and communicates with many others objects.
|
||||
- A behavior that is distributed between objects should be customizable without a subclassing.
|
||||
|
||||
Also, the mediator can be implemented with using the observer pattern, colleague classes act as Subjects, sending notifications to the mediator whenever they change state.
|
110
behavioral/mediator/main.go
Normal file
110
behavioral/mediator/main.go
Normal file
@ -0,0 +1,110 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"container/list"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
/*
|
||||
Mediator
|
||||
*/
|
||||
|
||||
// ChatRoomMediator main interface between colleague and mediator
|
||||
type ChatRoomMediator interface {
|
||||
JoinUser(uc UserColleague)
|
||||
SendMessage(uc UserColleague)
|
||||
}
|
||||
|
||||
// ChatRoom is a concrete mediator with all joined colleagues
|
||||
type ChatRoom struct {
|
||||
users *list.List
|
||||
}
|
||||
|
||||
// JoinUser join concrete colleagues to concrete mediator (ChatRoom)
|
||||
func (cr *ChatRoom) JoinUser(uc UserColleague) {
|
||||
cr.users.PushBack(uc)
|
||||
}
|
||||
|
||||
// SendMessage use mediator to communicate between colleagues
|
||||
func (cr *ChatRoom) SendMessage(uc UserColleague) {
|
||||
for e := cr.users.Front(); e != nil; e = e.Next() {
|
||||
if e.Value == uc {
|
||||
ct := time.Now().Format(time.Kitchen)
|
||||
fmt.Printf("|%s| %s -> : %s \n", ct, uc.GetName(), uc.GetMessage())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NewChatRoom creates concrete mediator
|
||||
func NewChatRoom() *ChatRoom {
|
||||
return &ChatRoom{list.New()}
|
||||
}
|
||||
|
||||
/*
|
||||
Colleague
|
||||
*/
|
||||
|
||||
// UserColleague implements colleague to communicate with mediator
|
||||
type UserColleague interface {
|
||||
GetName() string
|
||||
GetMessage() string
|
||||
}
|
||||
|
||||
// User represents concrete colleague
|
||||
type User struct {
|
||||
name string
|
||||
message string
|
||||
mediator ChatRoomMediator
|
||||
}
|
||||
|
||||
// GetMessage returns last wrote message
|
||||
func (u *User) GetName() string {
|
||||
return u.name
|
||||
}
|
||||
|
||||
// GetMessage returns last wrote message
|
||||
func (u *User) GetMessage() string {
|
||||
return u.message
|
||||
}
|
||||
|
||||
// WriteMessage concrete colleague send's message via mediator
|
||||
func (u *User) writeMessage(message string) {
|
||||
u.message = message
|
||||
|
||||
// Ask mediator to send message
|
||||
u.mediator.SendMessage(u)
|
||||
}
|
||||
|
||||
// AddUser will make relationship between concrete mediator and concrete colleague
|
||||
func AddUser(name string, chatRoom ChatRoomMediator) *User {
|
||||
// Create new colleague(user) and join mediator(room)
|
||||
user := &User{name: name, message: "", mediator: chatRoom}
|
||||
|
||||
// Join colleague(user) to mediator(room)
|
||||
chatRoom.JoinUser(user)
|
||||
|
||||
return user
|
||||
}
|
||||
|
||||
/*
|
||||
Showcase
|
||||
*/
|
||||
func main() {
|
||||
// Create mediator
|
||||
barrelHouse := NewChatRoom()
|
||||
|
||||
// Create colleagues and join to mediator
|
||||
JohnInBarrelHouse := AddUser("John Doe", barrelHouse)
|
||||
AlmaInBarrelHouse := AddUser("Alma", barrelHouse)
|
||||
|
||||
// Now colleagues will send messages via mediator
|
||||
JohnInBarrelHouse.writeMessage("Hello gophers")
|
||||
AlmaInBarrelHouse.writeMessage("Hey John!")
|
||||
JohnInBarrelHouse.writeMessage("Alma, let's discuss Mediator pattern?")
|
||||
|
||||
// Example of output
|
||||
// |8:33PM| John Doe -> : Hello gophers
|
||||
// |8:33PM| Alma -> : Hey John!
|
||||
// |8:34PM| John Doe -> : Alma, let's discuss Mediator pattern?
|
||||
}
|
Loading…
Reference in New Issue
Block a user