The Prototype pattern is a creational pattern that creates new software objects by copying an existing configured object through a common cloning object interface. A client keeps or selects a prototype and requests a copy, without naming the concrete software class or repeating its construction recipe.
It is useful when the concrete type is selected at runtime, when many objects share a configuration, or when reconstructing an initialized object is expensive. For example, a drawing application can duplicate a configured graphical object through the same interface for many shape classes. The contract must specify what is copied: nested mutable state may require a deep copy, whereas a shallow copy would retain reference aliasing. A copy should preserve the intended configuration while allowing independent changes where promised.
This is the Decorator pattern, a structural pattern.
Packages is a decorator object: it implements CableTV while holding another CableTV, to which its default queries delegate. Movies and HDChannels extend the price and description of the wrapped account. Because a wrapper itself satisfies CableTV, another wrapper can surround it; features combine without declaring a new software class for each possible package combination.In this UML class diagram, hollow triangles point toward the more general type; dashed lines denote realization of the
CableTV object interface. The plain association records that Packages retains one wrapped account, without claiming exclusive lifetime ownership.Add the following software class and client application to the supplied declarations. The inherited result type gives The printed accounts have costs
BasicPlan.cost an expected Double type, so its literal 30 is widened appropriately; no source change is needed.class Sports(account: CableTV) extends Packages(account) {
override def cost: Double = super.cost + 5.0
override def packages: String = super.packages + ", Sports"
}
object CheckCableTV {
def show(account: CableTV): Unit =
println(account.packages + ": GBP " + account.cost)
def main(args: Array[String]): Unit = {
val basic: CableTV = new BasicPlan
val movies: CableTV = new Movies(basic)
val hd: CableTV = new HDChannels(movies)
val sports: CableTV = new Sports(hd)
show(basic)
show(movies)
show(hd)
show(sports)
assert(sports.cost == 52.0)
assert(sports.packages == "Basic plan, Movies, HD channels, Sports")
}
}30.0, 40.0, 47.0, and 52.0, with each description extending the preceding one. The fully decorated account is Basic plan, Movies, HD channels, Sports, costing £52. The intermediate accounts remain available because wrapping constructs a new software object. [ref]Scala 2.11.12 method type inference implementation. methodSig and typesFromOverridden: inherited return type supplies the expected type while typing an overriding body
The Decorator pattern participants are:
CableTV: the component object interface, declaring the price and package description visible to clients.BasicPlan: the concrete component, supplying the initial £30 account and its description.Packages: the abstract decorator object, storing one component and forwarding its queries.MoviesandHDChannels, and the extensionSports: concrete decorator objects, adding respectively £10, £7, and £5 and appending their labels.
The checking application is the client that chooses and nests these participants. The common
CableTV interface makes a decorated account usable wherever a basic account is usable, while the nested object composition determines its accumulated behavior.A sequence diagram describes an interaction among participants using lifelines and ordered messages; time normally runs downward. Calls, replies, and execution intervals show a scenario such as the client asking a Sports wrapper for its cost, then that wrapper delegating through the inner packages to
BasicPlan and adding charges on return. Alternatives or loops can describe more than one trace.A state diagram describes states of an object or system and transitions triggered by events, possibly guarded by conditions and accompanied by actions. An account might move from active to suspended on a failed-payment event and back to active on payment. It describes allowed lifecycle behavior rather than the order of messages in one chosen interaction. Both are behavioral diagrams in UML.
Articles by others on the same topic
There are currently no matching articles.
