Hooray! After 3 years of work, I've finally released the ebook on design patterns! Check it out »
Bridge

Bridge in Go

Bridge is a structural design pattern that divides business logic or huge class into separate class hierarchies that can be developed independently.

One of these hierarchies (often called the Abstraction) will get a reference to an object of the second hierarchy (Implementation). The abstraction will be able to delegate some (sometimes, most) of its calls to the implementations object. Since all implementations will have a common interface, they’d be interchangeable inside the abstraction.

Conceptual Example

Say, you have two types of computers: Mac and Windows. Also, two types of printers: Epson and HP. Both computers and printers need to work with each other in any combination. The client doesn’t want to worry about the details of connecting printers to computers.

If we introduce new printers, we don’t want our code to grow exponentially. Instead of creating four structs for the 2*2 combination, we create two hierarchies:

  • Abstraction hierarchy: this will be our computers
  • Implementation hierarchy: this will be our printers

These two hierarchies communicate with each other via a Bridge, where the Abstraction (computer) contains a reference to the Implementation (printer). Both the abstraction and implementation can be developed independently without affecting each other.

computer.go: Abstraction

package main

type computer interface {
	print()
	setPrinter(printer)
}

mac.go: Refined abstraction

package main

import "fmt"

type mac struct {
	printer printer
}

func (m *mac) print() {
	fmt.Println("Print request for mac")
	m.printer.printFile()
}

func (m *mac) setPrinter(p printer) {
	m.printer = p
}

windows.go: Refined abstraction

package main

import "fmt"

type windows struct {
	printer printer
}

func (w *windows) print() {
	fmt.Println("Print request for windows")
	w.printer.printFile()
}

func (w *windows) setPrinter(p printer) {
	w.printer = p
}

printer.go: Implementation

package main

type printer interface {
	printFile()
}

epson.go: Concrete implementation

package main

import "fmt"

type epson struct {
}

func (p *epson) printFile() {
	fmt.Println("Printing by a EPSON Printer")
}

hp.go: Concrete implementation

package main

import "fmt"

type hp struct {
}

func (p *hp) printFile() {
	fmt.Println("Printing by a HP Printer")
}

main.go: Client code

package main

import "fmt"

func main() {

	hpPrinter := &hp{}
	epsonPrinter := &epson{}

	macComputer := &mac{}

	macComputer.setPrinter(hpPrinter)
	macComputer.print()
	fmt.Println()

	macComputer.setPrinter(epsonPrinter)
	macComputer.print()
	fmt.Println()

	winComputer := &windows{}

	winComputer.setPrinter(hpPrinter)
	winComputer.print()
	fmt.Println()

	winComputer.setPrinter(epsonPrinter)
	winComputer.print()
	fmt.Println()
}

output.txt: Execution result

Print request for mac
Printing by a HP Printer

Print request for mac
Printing by a EPSON Printer

Print request for windows
Printing by a HP Printer

Print request for windows

Bridge in Other Languages

Design Patterns: Bridge in Java Design Patterns: Bridge in C# Design Patterns: Bridge in C++ Design Patterns: Bridge in PHP Design Patterns: Bridge in Python Design Patterns: Bridge in Ruby Design Patterns: Bridge in Swift Design Patterns: Bridge in TypeScript