Created
June 6, 2019 07:51
-
-
Save santosh/ddef100bf4dfe397e1d872ef0333b502 to your computer and use it in GitHub Desktop.
Composition with Go. #golang
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import "fmt" | |
// Board represents a surface we can work on | |
type Board struct { | |
NailsNeeded int | |
NailsDriven int | |
} | |
// Mallet is a tool that pounds in nails. | |
type Mallet struct { | |
} | |
type Crowbar struct { | |
} | |
type Contractor struct { | |
} | |
// Toolbox can contain any number of tools | |
type Toolbox struct { | |
NailDriver | |
NailPuller | |
nails int | |
} | |
// NailDriver represents behavior to drive nails into a board | |
type NailDriver interface { | |
DriveNail(nailSupply *int, b *Board) | |
} | |
// NailPuller represents behavior to remove nails from the board | |
type NailPuller interface { | |
PullNail(nailSupply *int, b *Board) | |
} | |
// NailDrivePuller represents behavior to drive/remove nails from a board | |
type NailDrivePuller interface { | |
NailDriver | |
NailPuller | |
} | |
func (Mallet) DriveNail(nailSupply *int, b *Board) { | |
// Take the nail out of the supply | |
*nailSupply-- | |
// Pound the nail into the board | |
b.NailsDriven++ | |
fmt.Println("Mallet: pounded nail into the board.") | |
} | |
func (Crowbar) PullNail(nailSupply *int, b *Board) { | |
// Yank a nail out of the board | |
b.NailsDriven-- | |
// Put that nail back into the supply | |
*nailSupply++ | |
fmt.Println("Crowbar: yanked nail out of the board.") | |
} | |
// Fasten will drive nails into a board | |
func (Contractor) Fasten(d NailDriver, nailSupply *int, b *Board) { | |
for b.NailsDriven < b.NailsNeeded { | |
d.DriveNail(nailSupply, b) | |
} | |
} | |
// Unfasten will remove nails from a board | |
func (Contractor) Unfasten(p NailPuller, nailSupply *int, b *Board) { | |
for b.NailsDriven > b.NailsNeeded { | |
p.PullNail(nailSupply, b) | |
} | |
} | |
// ProcessBoards works against boards. | |
func (c Contractor) ProcessBoards(dp NailDrivePuller, nailSupply *int, boards []Board) { | |
for i := range boards { | |
b := &boards[i] | |
fmt.Printf("Contractor: examining board #%d: %+v\n", i+1, b) | |
switch { | |
case b.NailsDriven < b.NailsNeeded: | |
c.Fasten(dp, nailSupply, b) | |
case b.NailsDriven > b.NailsNeeded: | |
c.Unfasten(dp, nailSupply, b) | |
} | |
} | |
} | |
// displayState provide information about all the boards | |
func displayState(tb *Toolbox, boards []Board) { | |
fmt.Printf("Box: %#v\n", tb) | |
fmt.Println("Boards:") | |
for _, b := range boards { | |
fmt.Printf("\t%+v\n", b) | |
} | |
fmt.Println() | |
} | |
func main() { | |
// Inventory of old boards to remove, and the new boards | |
// that will replace them | |
boards := []Board{ | |
// Botten boards to be removed | |
{NailsDriven: 3}, | |
{NailsDriven: 1}, | |
{NailsDriven: 6}, | |
// Fresh boards to be fastened | |
{NailsNeeded: 6}, | |
{NailsNeeded: 9}, | |
{NailsNeeded: 4}, | |
} | |
tb := Toolbox{ | |
NailDriver: Mallet{}, | |
NailPuller: Crowbar{}, | |
nails: 10, | |
} | |
// Display the current state of our toolbox and boards | |
displayState(&tb, boards) | |
var c Contractor | |
c.ProcessBoards(&tb, &tb.nails, boards) | |
// Display the current state of our toolbox and boards | |
displayState(&tb, boards) | |
} | |
// Blog post at: https://www.ardanlabs.com/blog/2015/09/composition-with-go.html |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment