Structural Patterns «Prev Next»

Flyweight Pattern - Exercise

Objective

Refactor the course-project vehicle model so repeated immutable vehicle descriptions are canonical flyweights while each simulated vehicle occurrence retains independent extrinsic state. The finished design must demonstrate sharing through a factory without turning the domain model into a global cache.

Problem Statement

Assume a large simulation creates hundreds of thousands of vehicle events but uses a small catalog of vehicle types. Stable values such as category, dimensions, and normal velocity are candidates for intrinsic state. Event ID, direction, lane, arrival tick, current speed, and queue position are extrinsic and must not be stored in a shared flyweight.

The original exercise suggested subclassing a factory and assumed constant velocity. Your solution should make the state boundary explicit instead. Factory inheritance is optional. Composition is preferable when the only requirement is to substitute canonical creation behind an existing interface.

Implementation Requirements and Constraints

  1. Define an immutable VehicleType flyweight. In Java use final fields and defensive copies; in C++ expose const behavior and explicit ownership.
  2. Define a value-based canonical key containing every property that distinguishes one intrinsic description. Normalize case, units, and defaults before lookup.
  3. Implement a FlyweightVehicleFactory that returns the existing instance for an equal key and creates one instance on a miss.
  4. Do not expose the factory's mutable map or a public mutation method on the flyweight.
  5. Keep event identity and changing simulation data in a separate VehicleEvent or equivalent context type.
  6. Choose and document factory scope. A catalog owned by one simulation run is recommended; a static process-wide map requires a justified lifecycle and bounded key space.
  7. If concurrent creation is supported, prevent unsafe publication and define whether duplicate temporary construction is acceptable.
  8. Add read-only measurements for catalog size, hits, and misses so sharing can be verified.

Required Deliverables

Submit the flyweight class, canonical key, factory, event or context type, and tests. Include a brief state table identifying each field as intrinsic or extrinsic. Explain factory ownership, equality, thread-safety assumptions, and why the chosen key cannot merge semantically different vehicle descriptions. Your response should also state the workload assumption that motivates the optimization.

Testing and Verification

  • Request the same normalized key twice and assert that the factory returns the same canonical instance.
  • Request two meaningfully different keys and assert that their flyweights are distinct.
  • Create two events that share one flyweight and verify that their IDs, directions, and arrival times remain independent.
  • Attempt to mutate shared state and show that the type prevents it through its public API.
  • Exercise concurrent requests if the factory claims to be thread safe.
  • Generate a representative number of events and compare catalog cardinality with event count.

Evaluation Criteria

The solution is evaluated for a correct intrinsic/extrinsic split, immutable shared state, value-based canonicalization, bounded and explicit ownership, independent event identity, and deterministic tests. Merely caching mutable vehicle objects, comparing only reference identity, or placing direction and queue position inside the flyweight fails the pattern's correctness criteria.

Type your answer in the text area below and click Submit. Include both implementation and verification evidence in your response.