1
0
Fork 0
pr3-sose2026-fork/go/04-design-pattern/main.go

103 lines
3.5 KiB
Go

package main
import (
"fmt"
"gitty.informatik.th-mannheim.de/steger/pr3-sose2026/go/04-design-pattern/patterns"
)
// Counter is a concrete implementation of the Subject interface, which maintains a count and notifies observers whenever the count changes
type Counter struct {
patterns.Subject // Embedding the Subject interface allows Counter to inherit its methods and be treated as a Subject, enabling it to register observers and notify them of changes
Count int
}
// NewCounter creates and returns a new instance of the Counter struct, initializing the embedded Subject using the NewSubject function from the patterns package
func NewCounter() Counter {
return Counter{patterns.NewSubject(), 0}
}
// Inc increments the counter's count and notifies all registered observers of the change
func (c *Counter) Inc() {
c.Count++
c.Notify()
}
// Dec decrements the counter's count and notifies all registered observers of the change
func (c *Counter) Dec() {
c.Count--
c.Notify()
}
// CountPrinter is a concrete implementation of the Observer interface, which prints the current count whenever it receives an update notification from the Counter
type CountPrinter struct {
counter *Counter
}
func (cp *CountPrinter) Update() {
fmt.Println("count updated to ", cp.counter.Count)
}
var _ patterns.Observer = (*CountPrinter)(nil) // Compile-time assertion to ensure CountPrinter implements the Observer interface
// CounterHistory is a concrete implementation of the Observer interface, which maintains a history of the counter's count values whenever it receives an update notification from the Counter
type CounterHistory struct {
counter *Counter
history []int
}
// Update appends the current count value to the history slice whenever it receives an update notification from the Counter
func (ch *CounterHistory) Update() {
ch.history = append(ch.history, ch.counter.Count)
}
var _ patterns.Observer = (*CounterHistory)(nil) // Compile-time assertion to ensure CounterHistory implements the Observer interface
// The main function demonstrates the usage of the Counter, CountPrinter, and CounterHistory in an interactive command-line application.
// It allows the user to increment or decrement the counter and see the updates printed, while also maintaining a history of count values.
func main() {
// Create a new Counter instance, which will serve as the Subject in the Observer pattern
counter := NewCounter()
// Create a new CounterHistory instance and register it as an observer of the counter to track the history of count values
history := CounterHistory{&counter, []int{}}
counter.Register(&history)
// Create a new CountPrinter instance and register it as an observer of the counter to print the current count whenever it changes
printer := CountPrinter{&counter}
counter.Register(&printer)
printerRegistered := true
var input string
for {
fmt.Print("Enter a command (+: increment, -: decrement, q: quit): ")
fmt.Scanln(&input)
if len(input) != 1 {
fmt.Println("Please enter a single character.")
continue
}
switch input[0] {
case '+':
counter.Inc()
case '-':
counter.Dec()
case 'p':
// Toggle the registration of the CountPrinter observer. If it's currently registered, unregister it; if it's currently unregistered, register it.
if printerRegistered {
counter.Unregister(&printer)
} else {
counter.Register(&printer)
}
printerRegistered = !printerRegistered
case 'q':
fmt.Println("Exiting...")
fmt.Println(history.history)
return
default:
fmt.Println("Unknown command. Use '+', '-', or 'q'.")
}
}
}