forked from goinaction/code
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d849e6b
commit 96200b8
Showing
7 changed files
with
517 additions
and
254 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,97 +1,122 @@ | ||
// Sample program demonstrating struct composition. | ||
package main | ||
|
||
import "fmt" | ||
import ( | ||
"errors" | ||
"fmt" | ||
"math/rand" | ||
"time" | ||
) | ||
|
||
func init() { | ||
rand.Seed(time.Now().UnixNano()) | ||
} | ||
|
||
// ============================================================================= | ||
|
||
// EOD represents the end of the data stream. | ||
var EOD = errors.New("EOD") | ||
|
||
// Board represents a surface we can work on. | ||
type Board struct { | ||
NailsNeeded int | ||
NailsDriven int | ||
// Data is the structure of the data we are copying. | ||
type Data struct { | ||
Line string | ||
} | ||
|
||
// ============================================================================= | ||
|
||
// Mallet is a tool that pounds in nails. | ||
type Mallet struct{} | ||
// Xenia is a system we need to pull data from. | ||
type Xenia struct{} | ||
|
||
// DriveNail pounds a nail into the specified board. | ||
func (Mallet) DriveNail(nailSupply *int, b *Board) { | ||
*nailSupply-- | ||
b.NailsDriven++ | ||
fmt.Println("Mallet: pounded nail into the board.") | ||
// Pull knows how to pull data out of Xenia. | ||
func (Xenia) Pull(d *Data) error { | ||
switch rand.Intn(10) { | ||
case 1, 9: | ||
return EOD | ||
|
||
case 5: | ||
return errors.New("Error reading data from Xenia") | ||
|
||
default: | ||
d.Line = "Data" | ||
fmt.Println("In:", d.Line) | ||
return nil | ||
} | ||
} | ||
|
||
// Crowbar is a tool that removes nails. | ||
type Crowbar struct{} | ||
// Pillar is a system we need to store data into. | ||
type Pillar struct{} | ||
|
||
// PullNail yanks a nail out of the specified board. | ||
func (Crowbar) PullNail(nailSupply *int, b *Board) { | ||
b.NailsDriven-- | ||
*nailSupply++ | ||
fmt.Println("Crowbar: yanked nail out of the board.") | ||
// Store knows how to store data into Pillar. | ||
func (Pillar) Store(d Data) error { | ||
fmt.Println("Out:", d.Line) | ||
return nil | ||
} | ||
|
||
// ============================================================================= | ||
|
||
// Toolbox can contains a Mallet and a Crowbar. | ||
type Toolbox struct { | ||
Mallet | ||
Crowbar | ||
|
||
nails int | ||
// System wraps Xenia and Pillar together into a single system. | ||
type System struct { | ||
Xenia | ||
Pillar | ||
} | ||
|
||
// ============================================================================= | ||
|
||
// Contractor carries out the task of securing boards. | ||
type Contractor struct{} | ||
// IO provides support to copy bulk data. | ||
type IO struct{} | ||
|
||
// Fasten will drive nails into a board. | ||
func (Contractor) Fasten(m Mallet, nailSupply *int, b *Board) { | ||
for b.NailsDriven < b.NailsNeeded { | ||
m.DriveNail(nailSupply, b) | ||
// pull knows how to pull bulks of data from Xenia. | ||
func (IO) pull(x *Xenia, data []Data) (int, error) { | ||
for i := range data { | ||
if err := x.Pull(&data[i]); err != nil { | ||
return i, err | ||
} | ||
} | ||
|
||
return len(data), nil | ||
} | ||
|
||
// Unfasten will remove nails from a board. | ||
func (Contractor) Unfasten(cb Crowbar, nailSupply *int, b *Board) { | ||
for b.NailsDriven > b.NailsNeeded { | ||
cb.PullNail(nailSupply, b) | ||
// store knows how to store bulks of data from Pillar. | ||
func (IO) store(p *Pillar, data []Data) error { | ||
for _, d := range data { | ||
if err := p.Store(d); err != nil { | ||
return err | ||
} | ||
} | ||
} | ||
|
||
// ProcessBoards works against boards. | ||
func (c Contractor) ProcessBoards(tb *Toolbox, nailSupply *int, boards []Board) { | ||
for i := range boards { | ||
b := &boards[i] | ||
return nil | ||
} | ||
|
||
fmt.Printf("Contractor: examining board #%d: %+v\n", i+1, b) | ||
// Copy knows how to pull and store data from the System. | ||
func (io IO) Copy(sys *System, batch int) error { | ||
for { | ||
data := make([]Data, batch) | ||
|
||
switch { | ||
case b.NailsDriven < b.NailsNeeded: | ||
c.Fasten(tb.Mallet, nailSupply, b) | ||
i, err := io.pull(&sys.Xenia, data) | ||
if i > 0 { | ||
if err := io.store(&sys.Pillar, data[:i]); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
case b.NailsDriven > b.NailsNeeded: | ||
c.Unfasten(tb.Crowbar, nailSupply, b) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
} | ||
|
||
// ============================================================================= | ||
|
||
// main is the entry point for the application. | ||
func main() { | ||
boards := []Board{ | ||
{NailsDriven: 3}, | ||
{NailsNeeded: 2}, | ||
} | ||
|
||
tb := Toolbox{ | ||
Mallet: Mallet{}, | ||
Crowbar: Crowbar{}, | ||
nails: 10, | ||
// Initialize the system for use. | ||
sys := System{ | ||
Xenia: Xenia{}, | ||
Pillar: Pillar{}, | ||
} | ||
|
||
var c Contractor | ||
c.ProcessBoards(&tb, &tb.nails, boards) | ||
var io IO | ||
if err := io.Copy(&sys, 3); err != EOD { | ||
fmt.Println(err) | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,109 +1,134 @@ | ||
// Sample program demonstrating decoupling with interfaces. | ||
package main | ||
|
||
import "fmt" | ||
import ( | ||
"errors" | ||
"fmt" | ||
"math/rand" | ||
"time" | ||
) | ||
|
||
func init() { | ||
rand.Seed(time.Now().UnixNano()) | ||
} | ||
|
||
// ============================================================================= | ||
|
||
// EOD represents the end of the data stream. | ||
var EOD = errors.New("EOD") | ||
|
||
// Board represents a surface we can work on. | ||
type Board struct { | ||
NailsNeeded int | ||
NailsDriven int | ||
// Data is the structure of the data we are copying. | ||
type Data struct { | ||
Line string | ||
} | ||
|
||
// ============================================================================= | ||
|
||
// NailDriver represents behavior to drive nails into a board. | ||
type NailDriver interface { | ||
DriveNail(nailSupply *int, b *Board) | ||
// Puller declares behavior for pulling data. | ||
type Puller interface { | ||
Pull(d *Data) error | ||
} | ||
|
||
// NailPuller represents behavior to remove nails into a board. | ||
type NailPuller interface { | ||
PullNail(nailSupply *int, b *Board) | ||
// Storer declares behavior for storing data. | ||
type Storer interface { | ||
Store(d Data) error | ||
} | ||
|
||
// ============================================================================= | ||
|
||
// Mallet is a tool that pounds in nails. | ||
type Mallet struct{} | ||
// Xenia is a system we need to pull data from. | ||
type Xenia struct{} | ||
|
||
// DriveNail pounds a nail into the specified board. | ||
func (Mallet) DriveNail(nailSupply *int, b *Board) { | ||
*nailSupply-- | ||
b.NailsDriven++ | ||
fmt.Println("Mallet: pounded nail into the board.") | ||
// Pull knows how to pull data out of Xenia. | ||
func (Xenia) Pull(d *Data) error { | ||
switch rand.Intn(10) { | ||
case 1, 9: | ||
return EOD | ||
|
||
case 5: | ||
return errors.New("Error reading data from Xenia") | ||
|
||
default: | ||
d.Line = "Data" | ||
fmt.Println("In:", d.Line) | ||
return nil | ||
} | ||
} | ||
|
||
// Crowbar is a tool that removes nails. | ||
type Crowbar struct{} | ||
// Pillar is a system we need to store data into. | ||
type Pillar struct{} | ||
|
||
// PullNail yanks a nail out of the specified board. | ||
func (Crowbar) PullNail(nailSupply *int, b *Board) { | ||
b.NailsDriven-- | ||
*nailSupply++ | ||
fmt.Println("Crowbar: yanked nail out of the board.") | ||
// Store knows how to store data into Pillar. | ||
func (Pillar) Store(d Data) error { | ||
fmt.Println("Out:", d.Line) | ||
return nil | ||
} | ||
|
||
// ============================================================================= | ||
|
||
// Toolbox can contains a Mallet and a Crowbar. | ||
type Toolbox struct { | ||
Mallet | ||
Crowbar | ||
|
||
nails int | ||
// System wraps Xenia and Pillar together into a single system. | ||
type System struct { | ||
Xenia | ||
Pillar | ||
} | ||
|
||
// ============================================================================= | ||
|
||
// Contractor carries out the task of securing boards. | ||
type Contractor struct{} | ||
// IO provides support to copy bulk data. | ||
type IO struct{} | ||
|
||
// 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) | ||
// pull knows how to pull bulks of data from any Puller. | ||
func (IO) pull(p Puller, data []Data) (int, error) { | ||
for i := range data { | ||
if err := p.Pull(&data[i]); err != nil { | ||
return i, err | ||
} | ||
} | ||
|
||
return len(data), nil | ||
} | ||
|
||
// 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) | ||
// store knows how to store bulks of data from any Storer. | ||
func (IO) store(s Storer, data []Data) error { | ||
for _, d := range data { | ||
if err := s.Store(d); err != nil { | ||
return err | ||
} | ||
} | ||
} | ||
|
||
// ProcessBoards works against boards. | ||
func (c Contractor) ProcessBoards(tb *Toolbox, nailSupply *int, boards []Board) { | ||
for i := range boards { | ||
b := &boards[i] | ||
return nil | ||
} | ||
|
||
fmt.Printf("Contractor: examining board #%d: %+v\n", i+1, b) | ||
// Copy knows how to pull and store data from the System. | ||
func (io IO) Copy(sys *System, batch int) error { | ||
for { | ||
data := make([]Data, batch) | ||
|
||
switch { | ||
case b.NailsDriven < b.NailsNeeded: | ||
c.Fasten(tb.Mallet, nailSupply, b) | ||
i, err := io.pull(&sys.Xenia, data) | ||
if i > 0 { | ||
if err := io.store(&sys.Pillar, data[:i]); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
case b.NailsDriven > b.NailsNeeded: | ||
c.Unfasten(tb.Crowbar, nailSupply, b) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
} | ||
|
||
// ============================================================================= | ||
|
||
// main is the entry point for the application. | ||
func main() { | ||
boards := []Board{ | ||
{NailsDriven: 3}, | ||
{NailsNeeded: 2}, | ||
} | ||
|
||
tb := Toolbox{ | ||
Mallet: Mallet{}, | ||
Crowbar: Crowbar{}, | ||
nails: 10, | ||
// Initialize the system for use. | ||
sys := System{ | ||
Xenia: Xenia{}, | ||
Pillar: Pillar{}, | ||
} | ||
|
||
var c Contractor | ||
c.ProcessBoards(&tb, &tb.nails, boards) | ||
var io IO | ||
if err := io.Copy(&sys, 3); err != EOD { | ||
fmt.Println(err) | ||
} | ||
} |
Oops, something went wrong.