Creational patterns organize object creation; behavioral patterns organize interactions and responsibility for behavior. A creational pattern controls how concrete software objects are selected, instantiated, or shared, so clients need not hard-code the entire construction policy. Examples include the factory method pattern and the singleton pattern.
A behavioral pattern describes how objects collaborate, receive requests, or distribute an algorithm's behavior. For example the observer pattern lets a subject notify dependants after its state changes, and the strategy pattern supplies interchangeable implementations of an operation. This distinction concerns the pattern's principal responsibility; a system can use both kinds together.
The UML class diagram below uses dashed hollow-triangle arrows for trait realization and ordinary arrows for stored references or navigable associations. Visibility is
+ for public and - for private.GymEquipment implements Equipment. Performance and Prediction implement Functionality, each retaining one GymEquipment reference and registering itself with that equipment. Each equipment keeps a list of zero or more Functionality references; one functionality can in principle be registered with multiple equipment objects through the public method, although the supplied constructors register it only with their own equipment. Hence the generic registration association does not imply exclusive ownership or composition in UML.There are two traits, one concrete equipment software class, and two concrete observer software classes.
GymEquipment implements name, age, and weight as read-only values and overrides updateUserMeasures; the mutable measurement state and observer list are defined privately in Equipment. The diagram reflects the source, including deleteFunctionality returning a new list rather than mutating the stored list.The system uses the observer pattern with a pull-style update.
Equipment provides the subject interface and stores registered observers; GymEquipment is the concrete subject. Functionality is the observer interface, with Performance and Prediction as concrete observers. Their constructors subscribe them with addFunctionality(this).When
GymEquipment.updateUserMeasures is called, it first updates both measurements through super, then calls notifyFunctionalities. Every subscribed observer receives update() and reads the new measurements from its stored equipment reference. Performance calculates the current score; Prediction calculates the score at time time+5, keeping the other quantities fixed. Since observers are prepended to a list, notification follows reverse registration order.The source has two independent implementation defects.
deleteFunctionality(f) computes _functionalities diff List(f) but does not assign it back, so it does not actually unsubscribe anything. The prediction message also contains a physical newline inside an ordinary quoted Scala string in the PDF; executable code must join that string, concatenate pieces, or use a multiline string. Neither issue changes the intended observer pattern. The source's score is treated as the specified arithmetic expression, not as an independently validated physiological model.Introduce one shared
GymStandings singleton object. It stores the latest current-performance score for every participating GymEquipment, using the equipment reference as key, and returns every equipment object tied for the maximum score. Performance.update sends each freshly computed score to this object. The previous observer pattern and its prediction observer remain in use.The added
Performance -> GymStandings dependency means “reports to,” while GymStandings -> GymEquipment represents the equipment keys in its stored score map. GymStandings is an software object, so clients share its unique instance instead of constructing one standings object per machine. The singleton pattern centralizes the current scores and the maximum-score query. Equipment objects, rather than user names, are the keys because two users can have the same name. Scores are current readings, not an accumulation of all historical notifications; the largest reported score wins, with all ties retained.Use a Scala For example,
object for the singleton pattern, and replace Performance with a version that reports to it. This code plugs into the source's Equipment, GymEquipment, and Functionality definitions; Prediction can remain an independent observer once its displayed string line break is made executable.object GymStandings {
private var scores = Map.empty[GymEquipment, Int]
def record(e: GymEquipment, calories: Int): Unit = {
scores = scores.updated(e, calories)
}
def remove(e: GymEquipment): Unit = {
scores = scores - e
}
def leaders: List[(GymEquipment, Int)] = {
if (scores.isEmpty) Nil
else {
val best = scores.values.max
scores.toList.filter { case (_, score) => score == best }
.sortBy { case (equipment, _) => equipment.name }
}
}
}
class Performance(e: GymEquipment) extends Functionality {
private def calories: Int =
((e.age - e.weight + e.heartRate) * e.time) / 10
e.addFunctionality(this)
GymStandings.record(e, calories)
def update(): Unit = {
val current = calories
GymStandings.record(e, current)
println("Your current performance is: " + current + " calories burned.")
}
}new Performance(treadmill) and new Performance(bike) attach two observers; later GymStandings.leaders returns the leading equipment/score pairs. Initial registration records the equipment's present score, even before its first subsequent update. Recording replaces the same equipment's previous score, so repeated notifications do not multiply its contribution. The explicit remove supports taking an equipment object out of the comparison; detaching its observer when its session ends also prevents later re-registration through another notification. In the original single-threaded event model no extra synchronization is needed.All equipment observers report to the same standings software object, and
leaders returns every maximum or Nil if empty. The query takes to find/filter scores for active equipment objects, plus sorting the tied names for deterministic presentation by name; equal names may remain in either order and still denote distinct equipment. This uses the exact supplied integer score formula and its integer division; it does not substitute a different performance metric. A functioning unsubscribe operation, if required, must explicitly correct the source to _functionalities = _functionalities diff List(f). Articles by others on the same topic
There are currently no matching articles.

