Skip to content

Exam 1

Pattern Quiz

Problem 1

Imagine you are developing a drawing application that allows users to create various shapes, such as circles, rectangles, and triangles. Each shape has its own unique properties and behaviors. You want to design a system that can create these shapes dynamically based on user input. However, you don’t want the application to be tightly coupled to specific shape classes, as you may want to add new shapes in the future without modifying existing code.

Answer 1

In this scenario, the Factory Method Pattern can be used to create a factory for each type of shape (e.g., CircleFactory, RectangleFactory, TriangleFactory), and each factory will have a method for creating the respective shape. This way, when the user selects a shape to create, the application can use the appropriate factory to create the shape object without needing to know the exact class of the object beforehand. This decouples the creation of shapes from the rest of the application and makes it easier to extend the system with new shape types in the future.

classDiagram class Shape { + draw(): void } class Circle { + draw(): void } class Rectangle { + draw(): void } class Triangle { + draw(): void } abstract class ShapeFactory { + createShape(): Shape } class CircleFactory { + createShape(): Circle } class RectangleFactory { + createShape(): Rectangle } class TriangleFactory { + createShape(): Triangle } Shape <|.. Circle Shape <|.. Rectangle Shape <|.. Triangle ShapeFactory <|-- CircleFactory ShapeFactory <|-- RectangleFactory ShapeFactory <|-- TriangleFactory
  • Shape is the abstract product class representing a generic shape with a draw() method.
  • Circle, Rectangle, and Triangle are concrete product classes representing specific shapes, each with its own draw() method.
  • ShapeFactory is the abstract factory interface that declares a createShape() method for creating shapes.
  • CircleFactory, RectangleFactory, and TriangleFactory are concrete factory classes that implement ShapeFactory and provide specific implementations for creating circles, rectangles, and triangles, respectively.
Problem 2

You are developing a text editor application, and you want to provide users with the ability to apply various text formatting options to their documents. These formatting options include features like font styles (bold, italic, underline), text color, and highlighting. Additionally, you want to allow users to mix and combine these formatting options in a flexible and extensible manner.

Answer 2

In this scenario, the Decorator Design Pattern can be used effectively. You can define a base TextComponent class that represents the basic text content. Then, you can create decorator classes for each formatting option (e.g., BoldDecorator, ItalicDecorator, ColorDecorator) that inherit from the TextComponent class and add specific formatting behavior. These decorator classes can be stacked or combined in various ways to apply multiple formatting options to a text component.

For instance, to make a text bold and red, you can create a BoldDecorator and a ColorDecorator (for red) and stack them onto the base text component. This allows you to dynamically add or remove formatting options without modifying the underlying text content or the decorators themselves. The Decorator Pattern provides a flexible and reusable way to extend the behavior of individual text components while keeping the system open for future formatting options.

classDiagram class TextComponent { + display(): void } class ConcreteTextComponent { + display(): void } class TextDecorator { - component: TextComponent + display(): void } TextComponent <|-- ConcreteTextComponent TextComponent <|-- TextDecorator TextDecorator o-- TextComponent : contains class BoldDecorator { + display(): void } class ItalicDecorator { + display(): void } class ColorDecorator { - color: string + display(): void } TextDecorator <|-- BoldDecorator TextDecorator <|-- ItalicDecorator TextDecorator <|-- ColorDecorator
  • TextComponent is the base class representing the basic text content.
  • ConcreteTextComponent is a concrete implementation of TextComponent.
  • TextDecorator is the abstract decorator class that contains a reference to a TextComponent and adds formatting behavior.
  • BoldDecorator, ItalicDecorator, and ColorDecorator are concrete decorator classes that inherit from TextDecorator and provide specific formatting options.
Problem 3

You are developing a software application for a car manufacturing company that produces both electric and hybrid vehicles. Each type of vehicle (electric and hybrid) consists of multiple components, including an engine, battery, and charging system for electric vehicles and an engine, battery, and regenerative braking system for hybrid vehicles. Additionally, the company plans to expand its product line to include more vehicle types in the future, such as gasoline-powered and hydrogen fuel cell vehicles.

Answer 3

In this scenario, you need a design pattern that allows you to create families of related components (e.g., engines, batteries) for each type of vehicle (electric, hybrid, future vehicle types) without specifying the concrete classes of these components. The Abstract Factory Pattern can be used to define abstract factory interfaces for creating these components, and concrete implementations of these factory interfaces (e.g., ElectricVehicleFactory, HybridVehicleFactory) would provide specific component implementations for each type of vehicle. This way, when the car manufacturing company adds new vehicle types, they can simply create new concrete factory implementations without modifying existing code, ensuring that the system remains extensible and easily adaptable to changing requirements.

classDiagram class VehicleFactory { + createEngine(): Engine + createBattery(): Battery + createBrakingSystem(): BrakingSystem } class Engine { + start(): void } class Battery { + charge(): void } class BrakingSystem { + applyBrakes(): void } VehicleFactory <|-- ElectricVehicleFactory VehicleFactory <|-- HybridVehicleFactory Engine <|.. ElectricEngine Engine <|.. HybridEngine Battery <|.. ElectricBattery Battery <|.. HybridBattery BrakingSystem <|.. ElectricBrakingSystem BrakingSystem <|.. HybridBrakingSystem
  • VehicleFactory is the abstract factory interface that declares methods for creating components like engines, batteries, and braking systems.
  • Engine, Battery, and BrakingSystem are product interfaces representing different vehicle components.
  • ElectricVehicleFactory and HybridVehicleFactory are concrete factory classes that implement VehicleFactory and provide specific implementations for creating components for electric and hybrid vehicles.
  • ElectricEngine, HybridEngine, ElectricBattery, HybridBattery, ElectricBrakingSystem, and HybridBrakingSystem are concrete product classes representing components specific to electric and hybrid vehicles.
Problem 4

You are developing a stock trading platform that allows users to track the performance of various stocks in real-time. Users can create watch-lists of stocks they are interested in, and they want to receive immediate notifications whenever the price of a stock on their watch-list crosses a certain threshold, such as a predefined buy or sell price. Additionally, you want to allow users to customize these notifications based on their preferences.

Answer 4

In this scenario, the Observer Design Pattern can be highly beneficial. You can implement a system where each stock is an observable subject, and users’ watch-lists are the observers. When the price of a stock changes, it notifies all users who are observing that stock. Users can set their desired price thresholds and notification preferences when adding stocks to their watch-lists. This way, when a stock’s price crosses a threshold, the relevant users can be notified in real-time. The Observer Pattern helps keep the stock monitoring system flexible and extensible, allowing users to customize their watch-lists and notifications without modifying the core trading platform code.

classDiagram class Stock { + price: float + addSubscriber(observer: Subscriber): void + removeSubscriber(observer: Subscriber): void + notifySubscribers(): void + updatePrice(newPrice: float): void } class Subscriber { + name: string + thresholdPrice: float + notificationMethod: NotificationMethod + update(stock: Stock): void } abstract class NotificationMethod { + notify(user: Subscriber, stock: Stock): void } class EmailNotification { + notify(user: Subscriber, stock: Stock): void } class SMSNotification { + notify(user: Subscriber, stock: Stock): void } Stock "1" --> "*" Subscriber : has subscribers Subscriber --> NotificationMethod : uses NotificationMethod <|-- EmailNotification NotificationMethod <|-- SMSNotification
  • Stock represents a stock with a price that can change over time. It maintains a list of subscribers (users) who want to be notified when the stock price crosses a certain threshold.
  • Subscriber represents a user who is interested in a particular stock and has a thresholdPrice at which they want to be notified. Users can choose a notificationMethod (e.g., email or SMS) for receiving notifications.
  • NotificationMethod is an abstract class representing different notification methods. It has concrete implementations like EmailNotification and SMSNotification.
  • The associations between Stock and Subscriber represent that a stock can have multiple subscribers, and each subscriber can be interested in multiple stocks.
  • The associations between Subscriber and NotificationMethod represent that each subscriber uses a notification method.
Problem 5

You are designing a simulation software for testing and evaluating the safety measures in extreme weather conditions, such as hurricanes and blizzards. The software needs to generate realistic environmental conditions for testing various safety equipment and procedures. This includes simulating wind speed, temperature, humidity, precipitation, and visibility in a highly customizable manner.

Answer 5

In this unique scenario, the Abstract Factory Pattern is the best choice. You can create an abstract factory, EnvironmentalConditionsFactory, with methods for creating different aspects of environmental conditions, such as WindFactory, TemperatureFactory, HumidityFactory, PrecipitationFactory, and VisibilityFactory. Each concrete factory (e.g., ExtremeWindFactory, BlizzardTemperatureFactory, HeavyRainfallFactory) provides specific implementations of these aspects based on the chosen simulation scenario.

By using the Abstract Factory Pattern, you can ensure that the simulation software can generate a wide range of extreme weather conditions with varying parameters while maintaining a consistent interface for creating and configuring these conditions. This approach allows researchers and safety experts to evaluate equipment and procedures under various extreme conditions without needing to rewrite or modify the core simulation code for each scenario.

classDiagram class EnvironmentalConditionsFactory { + createWind(): Wind + createTemperature(): Temperature + createHumidity(): Humidity + createPrecipitation(): Precipitation + createVisibility(): Visibility } class Wind { + generateWindSpeed(): number } class Temperature { + generateTemperature(): number } class Humidity { + generateHumidity(): number } class Precipitation { + generatePrecipitationRate(): number } class Visibility { + generateVisibilityDistance(): number } EnvironmentalConditionsFactory <|-- ExtremeWeatherFactory EnvironmentalConditionsFactory <|-- BlizzardFactory EnvironmentalConditionsFactory <|-- HurricaneFactory Wind <|.. ExtremeWind Temperature <|.. BlizzardTemperature Humidity <|.. BlizzardHumidity Precipitation <|.. BlizzardPrecipitation Visibility <|.. BlizzardVisibility Wind <|.. HurricaneWind Temperature <|.. HurricaneTemperature Humidity <|.. HurricaneHumidity Precipitation <|.. HurricanePrecipitation Visibility <|.. HurricaneVisibility
  • EnvironmentalConditionsFactory is the abstract factory interface with methods for creating various aspects of environmental conditions.
  • Wind, Temperature, Humidity, Precipitation, and Visibility are abstract product classes representing different aspects of environmental conditions.
  • ExtremeWeatherFactory, BlizzardFactory, and HurricaneFactory are concrete factory classes that implement EnvironmentalConditionsFactory and provide specific implementations for creating environmental conditions for extreme weather scenarios.
  • ExtremeWind, BlizzardTemperature, BlizzardHumidity, BlizzardPrecipitation, BlizzardVisibility, HurricaneWind, HurricaneTemperature, HurricaneHumidity, HurricanePrecipitation, and HurricaneVisibility are concrete product classes representing specific environmental conditions for extreme weather scenarios.
Problem 6

You are developing a highly specialized application for generating custom mathematical visualizations used in advanced scientific research. Researchers need the ability to create complex mathematical plots and graphs with intricate notations, annotations, and dynamic data overlays. However, they require the capability to modify and extend the visualizations in real-time, adding new elements, calculations, or annotations on top of existing ones, without affecting the underlying data or calculations.

Answer 6

In this unique scenario, the Decorator Design Pattern can be a powerful solution. You can design a base class MathVisualization representing the core functionality for creating mathematical visualizations. Then, you can implement a set of concrete decorator classes (e.g., NotationDecorator, AnnotationDecorator, OverlayDecorator) that inherit from MathVisualization and add specific visualization elements and behaviors. Researchers can apply these decorators to their mathematical plots in a modular and customizable way, stacking and combining them to create intricate and highly specialized visualizations. This approach ensures that the visualization system remains exceptionally flexible and adaptable to the complex and evolving needs of advanced scientific research, even though it is a relatively rare use case.

classDiagram class MathVisualization { + render(): void } class ConcreteMathVisualization { + render(): void } class MathVisualizationDecorator { - visualization: MathVisualization + render(): void } class NotationDecorator { - visualization: MathVisualization + render(): void } class AnnotationDecorator { - visualization: MathVisualization + render(): void } class OverlayDecorator { - visualization: MathVisualization + render(): void } MathVisualization <|-- ConcreteMathVisualization MathVisualization <|-- MathVisualizationDecorator MathVisualizationDecorator <|-- NotationDecorator MathVisualizationDecorator <|-- AnnotationDecorator MathVisualizationDecorator <|-- OverlayDecorator ConcreteMathVisualization --> MathVisualization : contains
  • MathVisualization is the base class representing the core functionality for creating mathematical visualizations with a render() method.
  • MathVisualizationDecorator is the abstract decorator class that inherits from MathVisualization and has a reference to a MathVisualization object, allowing it to stack multiple decorators and apply them in sequence.
  • ConcreteMathVisualization is a concrete visualization class that inherits from MathVisualization.
  • NotationDecorator, AnnotationDecorator, and OverlayDecorator are concrete decorator classes that inherit from MathVisualizationDecorator and provide specific visualization elements and behaviors.
Problem 7

You are developing a smart agricultural system that monitors and manages a large greenhouse with various crops. The greenhouse environment, including temperature, humidity, and light levels, needs to be constantly monitored to ensure optimal growing conditions for different plant species. When environmental parameters fall outside predefined ranges, corrective actions, such as adjusting heating or irrigation systems, need to be taken immediately to prevent crop damage.

Answer 7

In this scenario, the Observer Design Pattern is an ideal solution. Each environmental sensor (temperature sensor, humidity sensor, light sensor) acts as a subject (observable) that notifies a set of controllers (observers) responsible for making real-time adjustments. Controllers can be responsible for specific aspects like heating, irrigation, and ventilation. When sensor readings indicate a need for action, the sensors notify the appropriate controllers, which then take corrective measures to maintain the greenhouse environment within the desired parameters. This design ensures that the agricultural system can respond promptly to changing conditions and maintain optimal growing conditions for different plant species.

classDiagram interface Subject { + attach(observer: Observer): void + detach(observer: Observer): void + notify(): void } interface Observer { + update(sensor: Sensor): void } class Sensor { + readData(): void } class TemperatureSensor { + readData(): void } class HumiditySensor { + readData(): void } class LightSensor { + readData(): void } class Controller { + controlEnvironment(sensor: Sensor): void } Subject <|.. Sensor Subject <|.. Controller Observer <|.. Controller Sensor --> Subject : (attaches/detaches) Controller --> Subject : (notifies)
  • Subject is the interface representing the subject (observable) with methods for attaching, detaching, and notifying observers.
  • Observer is the interface representing the observer with an update method to receive updates from sensors.
  • Sensor is the base class for environmental sensors, and it implements the Subject interface. Each sensor can attach multiple controllers as observers.
  • TemperatureSensor, HumiditySensor, and LightSensor are concrete sensor classes.
  • Controller is the class representing controllers responsible for taking corrective actions. It implements the Observer interface and can be notified by sensors when environmental conditions change.
Problem 8

You are designing a graphical user interface (GUI) framework for a software development toolkit. This framework needs to support multiple operating systems (e.g., Windows, macOS, Linux) and multiple UI toolkits (e.g., WinForms for Windows, Cocoa for macOS, GTK for Linux) to provide a consistent and native look and feel on each platform. Each combination of operating system and UI toolkit has its own set of UI components (e.g., buttons, text fields, windows) with distinct behaviors and appearances.

Answer 8

In this complex scenario, you need a design pattern that allows you to create families of UI components for different combinations of operating systems and UI toolkits without tightly coupling the application code to specific GUI libraries. The Abstract Factory Pattern can be instrumental in achieving this. You can define abstract factory interfaces for creating UI components (e.g., ButtonFactory, TextFieldFactory) and provide concrete factory implementations for each combination (e.g., WindowsWinFormsFactory, macOSCocoaFactory, LinuxGTKFactory).

By using the Abstract Factory Pattern, your GUI framework can dynamically select the appropriate factory at runtime based on the target operating system and UI toolkit, ensuring that the correct UI components are created without introducing conditional statements or platform-specific code throughout the application. This results in a highly modular and maintainable system capable of supporting a wide range of platform combinations without code duplication.

classDiagram class GUIFactory { + createButton(): Button + createTextField(): TextField + createWindow(): Window } class Button { + render(): void } class TextField { + render(): void } class Window { + render(): void } GUIFactory <|-- WinFormsFactory GUIFactory <|-- CocoaFactory GUIFactory <|-- GTKFactory Button <|.. WinFormsButton Button <|.. CocoaButton Button <|.. GTKButton TextField <|.. WinFormsTextField TextField <|.. CocoaTextField TextField <|.. GTKTextField Window <|.. WinFormsWindow Window <|.. CocoaWindow Window <|.. GTKWindow
  • GUIFactory is the abstract factory interface that declares methods for creating GUI components like buttons, text fields, and windows.
  • Button, TextField, and Window are product interfaces representing different GUI components.
  • WinFormsFactory, CocoaFactory, and GTKFactory are concrete factory classes that implement GUIFactory and provide specific implementations for creating GUI components for different operating systems and UI toolkits.
  • WinFormsButton, CocoaButton, GTKButton, WinFormsTextField, CocoaTextField, GTKTextField, WinFormsWindow, CocoaWindow, and GTKWindow are concrete product classes representing GUI components specific to each combination of operating system and UI toolkit.
Problem 9

You are developing an e-commerce platform that offers various payment methods to customers, including credit cards, digital wallets, and bank transfers. Each payment method has its own unique authentication process and transaction handling requirements. Additionally, you want to allow customers to switch between different payment methods during the checkout process seamlessly.

Answer 9

In this scenario, the Strategy Design Pattern is an excellent choice. You can define a common payment interface and create multiple concrete payment strategy classes (e.g., CreditCardPaymentStrategy, WalletPaymentStrategy, BankTransferPaymentStrategy) that implement this interface. Each strategy encapsulates the specific behavior required for authentication and processing transactions for a particular payment method.

During the checkout process, the e-commerce platform can dynamically switch between payment strategies based on the customer’s choice, ensuring that the correct payment method’s behavior is executed without the need for complex conditional statements or code duplication. This design allows for easy extensibility, as new payment methods can be added by creating new strategy classes without modifying the existing payment processing code.

classDiagram class PaymentStrategy { + processPayment(amount: number): void + authenticatePayment(): void } class CreditCardPaymentStrategy { + processPayment(amount: number): void + authenticatePayment(): void } class WalletPaymentStrategy { + processPayment(amount: number): void + authenticatePayment(): void } class BankTransferPaymentStrategy { + processPayment(amount: number): void + authenticatePayment(): void } class ShoppingCart { + setPaymentStrategy(strategy: PaymentStrategy): void + checkout(amount: number): void } PaymentStrategy <|.. CreditCardPaymentStrategy PaymentStrategy <|.. WalletPaymentStrategy PaymentStrategy <|.. BankTransferPaymentStrategy PaymentStrategy <|-- ShoppingCart : uses
  • PaymentStrategy is the interface representing the common payment strategy with methods for processing payments and authenticating payments.
  • CreditCardPaymentStrategy, WalletPaymentStrategy, and BankTransferPaymentStrategy are concrete strategy classes that implement the PaymentStrategy interface, each providing specific behavior for their respective payment methods.
  • ShoppingCart is a class representing the e-commerce shopping cart. It can be configured with a payment strategy using setPaymentStrategy, and the checkout method initiates the payment processing using the selected strategy.
Problem 10

You are developing a graphic design software that allows users to create and edit images. Users can apply various filters and effects to images, such as blurring, sharpening, color correction, and text overlay. However, you want to provide users with the ability to apply multiple filters and effects in a flexible and customizable way, allowing them to combine and reorder these transformations easily.

Answer 10

In this scenario, the Decorator Design Pattern is an excellent choice. You can create a base ImageFilter class representing the core image processing functionality. Then, you can implement a set of concrete decorator classes (e.g., BlurFilter, SharpenFilter, ColorCorrectionFilter, TextOverlayFilter) that inherit from ImageFilter and add specific image processing behaviors. Users can apply multiple filters to an image and customize their order, stacking and combining them to achieve the desired visual effects. This design ensures that the image processing system remains highly extensible and allows users to experiment with various combinations of filters and effects to achieve their creative goals.

classDiagram class Image { + apply(): void } class ImageFilter { - image: Image + apply(): void } class ConcreteImage { + apply(): void } class BlurFilter { - image: Image + apply(): void } class SharpenFilter { - image: Image + apply(): void } class ColorCorrectionFilter { - image: Image + apply(): void } class TextOverlayFilter { - image: Image + apply(): void } Image <|-- ImageFilter ImageFilter <|-- ConcreteImage ImageFilter <|-- BlurFilter ImageFilter <|-- SharpenFilter ImageFilter <|-- ColorCorrectionFilter ImageFilter <|-- TextOverlayFilter ConcreteImage --> Image : contains
  • Image is the base class representing the core image functionality, with an apply() method.
  • ImageFilter is the abstract decorator class that inherits from Image and has a reference to an Image object, allowing it to stack multiple filters and apply them in sequence.
  • ConcreteImage is a concrete image class that inherits from Image.
  • BlurFilter, SharpenFilter, ColorCorrectionFilter, and TextOverlayFilter are concrete decorator classes that inherit from ImageFilter and provide specific image processing behaviors.
Problem 11

You are developing a smart home automation system that controls various devices, including lights, thermostats, and security cameras. Users can create automation rules to trigger actions based on specific events, such as motion detection, temperature changes, or manual input. Users want to receive real-time updates and notifications whenever these events occur, and they want the flexibility to create complex automation scenarios without tightly coupling the devices and rules.

Answer 11

In this scenario, the Observer Design Pattern is exceptionally well-suited. Each device, such as a motion sensor or thermostat, can act as a subject (observable) that notifies all registered automation rules (observers) when relevant events occur. Users can define custom automation rules that observe these devices and take actions like turning on lights or adjusting the thermostat when specific events are detected. This approach ensures that users can easily create and manage automation scenarios while keeping the automation system flexible and extensible. The Observer Pattern allows for real-time event-driven updates and notifications without creating complex interdependencies between devices and rules.

classDiagram class Device { + name: string + observers: Observer[] + attach(observer: Observer): void + detach(observer: Observer): void + notify(): void + getState(): string + setState(state: string): void } class Observer { + name: string + update(device: Device): void } class AutomationRule { + name: string + condition: string + action: string + applyRule(device: Device): void } Device --> Observer : 0..* observes Device <|-- MotionSensor : detects Device <|-- Thermostat : controls Device <|-- Light : controls Observer --> Device : observes Observer <|-- AutomationRule : triggers class MotionSensor { + detectMotion(): void } class Thermostat { + setTemperature(temperature: number): void } class Light { + turnOn(): void + turnOff(): void }
  • Device is the subject (observable) class representing various smart home devices. It maintains a list of observers (automation rules) that need to be notified when specific events occur.
  • Observer is the observer interface that defines the update method, which is called when a device’s state changes.
  • AutomationRule represents automation rules created by users. These rules specify conditions and actions to be taken based on device events.
  • MotionSensor, Thermostat, and Light are concrete device classes that inherit from Device. Each device can be observed by multiple automation rules.
Problem 12

You are developing a video game where players can choose different character classes, such as warriors, mages, and archers. Each character class has its own unique abilities, stats, and equipment. Players can switch between character classes during the game or create new characters of the same class. You want to implement a flexible system for creating characters without tightly coupling the game logic to specific character class implementations.

Answer 12

In this scenario, the Factory Method Pattern can be employed to create character objects. Each character class (e.g., Warrior, Mage, Archer) would have its own factory (e.g., WarriorFactory, MageFactory, ArcherFactory) responsible for creating instances of that specific class. When a player wants to create or switch to a character, you can use the appropriate factory to generate the character object, ensuring that the game’s core logic doesn’t need to be modified every time a new character class is added. This allows for easy expansion of the game with additional character classes while maintaining code flexibility and scalability.

classDiagram class Character { + attack(): void + defend(): void } class Warrior { + attack(): void + defend(): void } class Mage { + attack(): void + defend(): void } class Archer { + attack(): void + defend(): void } abstract class CharacterFactory { + createCharacter(): Character } class WarriorFactory { + createCharacter(): Warrior } class MageFactory { + createCharacter(): Mage } class ArcherFactory { + createCharacter(): Archer } Character <|.. Warrior Character <|.. Mage Character <|.. Archer CharacterFactory <|-- WarriorFactory CharacterFactory <|-- MageFactory CharacterFactory <|-- ArcherFactory
  • Character is the abstract product class representing a generic character in the game with attack() and defend() methods.
  • Warrior, Mage, and Archer are concrete product classes representing specific character classes, each with its own attack() and defend() methods.
  • CharacterFactory is the abstract factory interface that declares a createCharacter() method for creating characters.
  • WarriorFactory, MageFactory, and ArcherFactory are concrete factory classes that implement CharacterFactory and provide specific implementations for creating warrior, mage, and archer characters, respectively.