The Strategy pattern is a behavioral pattern that encapsulates alternative algorithms behind a shared object interface. A context holds a strategy and delegates the relevant operation to it, letting the chosen algorithm vary independently of its caller.
Use it when the same task has interchangeable policies, such as alternative pricing or route-selection algorithms. Supplying a different strategy changes the policy without expanding a chain of type tests in the context, and each policy can be checked independently. Object composition makes the selected strategy replaceable; clients rely on its contract rather than on one concrete implementation.
This is the Observer pattern, a behavioral pattern.
Service stores subscribers through the Company object interface. SomeService.updateValue first changes the underlying value and then sends a notification to every registered company; each company's meth() queries the new value and computes its own response. This is a pull-style notification: the message announces the change, while the observer reads the data from its retained subject reference.The UML class diagram shows the subject's collection of observers and the added concrete observer. Each concrete company also retains the
SomeService reference shown in its attributes; notifications call meth() through Company.Use an unscaled value both initially and in every callback:Initializing
class NonProfit(service: SomeService) extends Company {
private var v: Double = service.value
service.addCompany(this)
override def meth(): Unit = {
v = service.value
printf("New service value: %f\n", v)
}
}v before registration prevents a callback from observing an uninitialized field if registration is later extended to notify immediately. For a service initially valued at 100.0, this initializes v to 100.0; after updateValue(125.0), the callback sets v to 125.0 and prints New service value: 125.000000 under a decimal-point locale. The NonProfit update uses factor one.The word “always” requires a qualification in the supplied design. In the intended single-threaded notification protocol, holds after construction and after a completed
SomeService.updateValue. However, the printed public value_= setter changes the subject without calling sendMessage(). Calling service.value = ... can therefore leave every cached observer value stale. No implementation that merely caches v in meth() can guarantee literal equality after that unannounced change. If equality on every query is required, replace the field by private def v: Double = service.value, retaining registration and the same printing callback; alternatively every mutation route must notify observers. The source's distinct private/public company multipliers are not changed.The Observer pattern participants are:
Service: the subject abstraction, owning the current value and registeredCompanyreferences, and providing registration and notification operations.SomeService: the concrete subject, makingupdateValuenotify after establishing the new subject state.Company: the observer object interface, declaring themeth()callback.PrivateCompanyandPublicCompany, together with the extensionNonProfit: concrete observers, registering themselves, retaining their subject, and updating their own values on notification.
The printed
PrivateCompany starts with factor but uses factor in its callback; PublicCompany starts with factor but later uses . These are the actual source behaviors, not a uniform pricing rule inferred from their names. The subject stores a list and prepends new subscriptions, so notification occurs in reverse registration order. Dependence on the Company interface lets the subject notify new observer types without naming their concrete classes. The omitted ... portions in the printed figure do not prevent identifying these roles or implementing the added observer.True. A named software design pattern supplies shared vocabulary for recurring arrangements of responsibilities and interactions. Saying “observer” can identify subject registration and callbacks without first reproducing every implementation detail, provided developers still agree on the actual contract.
False as a general claim. An appropriately chosen software design pattern can make expected variation easier: a new strategy or decorator can be supplied through an existing object interface. An unnecessary pattern can add indirection and make some changes harder, so applying one is not an automatic guarantee of flexibility either.
True. A small proof-of-concept implementation makes the participants, delegation, and extension points of a software design pattern concrete. Trying a second strategy, an extra decorator, or another observer tests what changes locally and what assumptions remain. This supports learning when the arrangement is useful; it does not establish that every production system needs it.
True. Refactoring an existing implementation toward a software design pattern can be preferable once repeated structure and actual variation are visible. Existing behavior supplies a concrete contract to preserve, and tests can check that preservation. Starting from a pattern is appropriate when its problem is already established, but the pattern's name alone is not evidence that its extra structure is needed.
Articles by others on the same topic
There are currently no matching articles.
