Design a Reconfigurable Data Processor

Architect a Strategy pattern system using UML class diagrams in draw.io.

Introduction

30 Second Summary

Think about how a smartphone can switch between camera modes without needing a completely different phone for each one. Software systems need the same kind of flexibility.

In this project, you will design a UML class diagram that architects a data processor capable of switching between processing modes and database connections at runtime, using the Strategy design pattern.

What You'll Build

Imagine showing your project lead an architecture diagram where adding a brand new processing mode or database requires zero changes to existing code. They can see immediately that your design is clean, extensible, and follows professional standards.

By the end of this project, you'll have:

  • A Processor class that delegates behavior to swappable strategy objects instead of using rigid if/else logic, so you can reconfigure it at runtime.
  • Two interface hierarchies (one for processing modes, one for database connections) that make adding new implementations trivial.
  • Proper UML notation showing composition, realization, and dependency relationships that any engineer can read.
  • A submission-ready PDF export of your completed diagram, proving you can architect extensible, SOLID-compliant systems.
  • Secret Mission: Add a ProcessorFactory class that separates object creation from configuration logic using the Factory pattern.

Are there any prerequisites?

You should have a basic understanding of Java classes and interfaces. Specifically, you should know what a class is, what an interface is, and what "implements" means. No prior experience with design patterns or UML is needed.

Before We Start

Before we dive in, let's lock in what you're about to build and why it matters.

Think about what would happen if you hardcoded every processing mode and every database connection directly into a single Processor class. Every time your team adds a new mode or swaps a database, someone has to crack open that class and rewrite its internals.

Set Up draw.io with UML Shape Libraries

Before you can design the data processor architecture, you need a diagramming tool that supports proper UML notation. UML class diagrams use specific shapes and connectors that carry precise meaning, so a general-purpose drawing app won't cut it.

In this step, you'll set up draw.io, a free browser-based diagramming tool with built-in UML 2.5 shape libraries. No installation or account required.

In this step, get ready to:
  • Open draw.io and create a new diagram file.
  • Enable the UML and UML 2.5 shape libraries.
  • Verify that UML class shapes and connectors are available.
Open draw.io and create a new diagram

draw.io runs entirely in the browser. You'll create a blank diagram saved to your local device so you don't need any cloud accounts.

  • Open your browser and navigate to https://app.diagrams.net.
  • draw.io will prompt you to choose where to save your diagrams. Select Device to save files locally on your computer.
  • Click Create New Diagram.
  • In the template manager, type DataProcessorArchitecture in the filename field.
  • Make sure Blank Diagram is selected as the template.
  • Click Create.

You should see a blank white canvas with a toolbar at the top and a shapes panel on the left.

Why save to Device?

Saving to your device means your diagram file lives as a .drawio file on your computer. You don't need a Google Drive, OneDrive, or any other cloud account to complete this project.

Not seeing the storage prompt?

If you've used draw.io before, it may skip the storage dialog and go straight to the editor. That's fine. Your previous storage choice still applies, or you can change it later via the menu.

If the page doesn't load at all, check your internet connection and try refreshing. Help me troubleshoot draw.io not loading.

Enable the UML shape libraries

By default, draw.io shows general-purpose shapes like flowchart boxes and arrows. You need to enable the dedicated UML libraries to get class diagram shapes with the correct three-section structure.

  • Click + More Shapes at the bottom of the left panel.
  • In the dialog that appears, scroll down to the Software section.
  • Enable the UML checkbox.
  • Enable the UML 2.5 checkbox.
  • Click Apply to return to the diagram editor.

The left panel now shows UML class shapes. You should see rectangles divided into three sections: class name at the top, attributes in the middle, methods at the bottom.

What do these shape libraries give you?

The UML libraries add shapes specifically designed for class diagrams. Each class shape has three compartments that map to the standard UML notation: name, attributes, and operations.

The libraries also include UML-specific connectors like realization arrows (dashed line with hollow triangle) and composition arrows (solid line with filled diamond). These connectors carry specific meanings you'll use throughout the project.

Don't see UML shapes in the left panel?

Make sure you clicked Apply after enabling both checkboxes. If you closed the dialog without applying, the libraries won't load.

If you can't find the Software section, scroll further down in the shape library dialog. It's below the General and Networking sections.

Help me find the UML shape libraries in draw.io.

Verify the UML shapes are available

Before you start building the diagram, confirm that all the shapes and connectors you need are accessible.

  • In the left panel, scroll through the UML shape library sections.
  • Hover over a class shape to see a larger preview. The class shape has three sections: class name at the top, attributes in the middle, methods at the bottom.
  • Look for shapes labeled Class and Interface in the library.
  • Confirm you can also see relationship arrows (various line styles with different arrowheads).

What do you expect to see in the left panel right now? Think about what shapes a UML class diagram needs before you check.

You should see UML class shapes (three-section rectangles) and UML connector types including various relationship arrows. Your canvas is still blank, and that's correct. You're ready to start drawing.

Your diagramming environment is ready. Next up, you'll draw the Processor class and the given classes that it depends on.

Draw the Processor Class and Given Classes

The Processor is the heart of your data processing system. It is the central class that everything else connects to.

Drawing it first gives you something concrete on the canvas and establishes the "context" class in the Strategy pattern. You also need three pre-existing classes (DataPoint, ModeIdentifier, DatabaseIdentifier) that another engineer provides. Your Processor depends on all three.

In this step, get ready to:
  • Draw the Processor class with its attributes and methods.
  • Draw the three given classes that Processor depends on.
  • Connect Processor to each given class with dependency arrows.
Draw the Processor class

The Processor class is the context in the Strategy pattern. It holds references to swappable strategy objects rather than implementing behavior directly.

  • In the left panel, find a UML class shape (the three-section rectangle with a name, attributes, and methods section).
  • Drag a class shape onto the center of your canvas.
  • Double-click the class name section at the top and type Processor.

Now add the attributes. The default class shape comes with a placeholder row in the attributes section.

  • Double-click the first attribute row and replace the text with:
- mode: ProcessingMode
  • Select that attribute row, then press Ctrl+Enter (Windows) or Cmd+Enter (macOS) to clone it.
  • Double-click the new row and replace it with:
- database: DatabaseConnection

What do the minus signs mean?

In UML notation, - means private visibility and + means public. The Processor's attributes are private because other classes should not directly change which mode or database is active.

Next, add the methods. The class shape should have a methods section at the bottom with a placeholder row.

  • Double-click the first method row and replace it with:
+ configure(mode: ModeIdentifier, db: DatabaseIdentifier): void
  • Clone this row with Ctrl+Enter (Windows) or Cmd+Enter (macOS).
  • Double-click the new row and replace it with:
+ process(data: DataPoint): void

You should now see a Processor class on your canvas with two private attributes and two public methods.

What does this class do?

The configure method lets external code swap the Processor's behavior at runtime by passing enum identifiers. The process method delegates work to whatever mode is currently plugged in.

This is what makes the design dynamically reconfigurable. The Processor never needs to be modified to support new modes or databases.

Don't see separate attribute and method sections?

Make sure you dragged a detailed UML class shape (the one with three visible sections separated by lines), not a simple rectangle. Look in the UML shape library for the shape with visible dividers between name, attributes, and methods.

If you only see one text area, delete the shape and try dragging the "Class" shape from the UML section of the left panel instead.

help me find the correct UML class shape with three sections in draw.io

Draw the given classes

Your Processor doesn't exist in isolation. It receives DataPoint objects, and its configure method accepts enum values that identify which mode and database to use. These three classes are provided by another engineer on your team.

  • Drag a new class shape onto the canvas, off to one side of the Processor.
  • Double-click the class name and type DataPoint.
  • Delete any placeholder attribute and method rows by selecting each row, right-clicking, and choosing Delete. Leave the attributes and methods sections empty since this class is provided by another engineer.

Now create the two enumeration classes. These represent the set of valid identifiers the Processor accepts.

  • Drag another class shape onto the canvas near DataPoint.
  • Double-click the class name and type <<enumeration>> on the first line, then press Shift+Enter to add a line break, and type ModeIdentifier on the second line.
  • In the attributes section, add three rows with the enum values:
DUMP
PASSTHROUGH
VALIDATE
  • Drag one more class shape onto the canvas.
  • Set the class name to <<enumeration>> on the first line, Shift+Enter for a line break, then DatabaseIdentifier on the second line.
  • In the attributes section, add three rows with the enum values:
POSTGRES
REDIS
ELASTIC

You now have four class shapes on your canvas. The Processor has full detail, DataPoint is empty, and the two enumerations list their valid values.

What is the <<enumeration>> stereotype?

In UML, text inside << >> is called a stereotype. It labels a class with a special role. The <<enumeration>> stereotype tells anyone reading your diagram that this class defines a fixed set of named constants, not a regular class with behavior.

Enum values not showing up?

Make sure you are adding the enum values in the attributes (middle) section of the class shape, not the methods (bottom) section. Each value should be on its own row. Clone rows with Ctrl+Enter (Windows) or Cmd+Enter (macOS) if you need more.

help me add multiple rows to my UML class shape in draw.io

Add dependency arrows from Processor to the given classes

The Processor uses DataPoint as a parameter, and references ModeIdentifier and DatabaseIdentifier in its configure method. In UML, "uses" is represented by a dependency relationship: a dashed line with an open arrow.

  • In the UML shape library on the left panel, scroll to find the connector shapes. Look for the dashed line with an open arrow (labeled "Dependency" or "Use" when you hover over it).
  • Click on or drag the dependency connector from the library.
  • Drag one end onto the Processor class (drop it when the class edge highlights in blue) and the other end onto the DataPoint class.
  • The arrow should point from Processor toward DataPoint. The open arrow tip should be at the DataPoint end.
  • Repeat this process to draw a dependency arrow from Processor to ModeIdentifier.
  • Draw one more dependency arrow from Processor to DatabaseIdentifier.

What does a dependency arrow mean?

A dependency (dashed line with open arrow) means: if the target class changes, it might affect the source class. The Processor depends on DataPoint because it receives data of that type. It depends on the enumerations because it uses those values to decide which strategies to configure.

The arrow points toward the class being depended on. Processor depends on DataPoint, so the arrow flows from Processor to DataPoint.

Faster connector drawing

Instead of dragging connectors from the library each time, you can hover over the Processor shape and drag from one of the four directional arrows that appear. Then change the connector style to dashed and set the arrowhead to an open arrow in the Style tab of the format panel.

Before you move on, take a moment to predict: how many shapes and connectors should be on your canvas right now?

You should see 4 class shapes (Processor, DataPoint, ModeIdentifier, DatabaseIdentifier) connected by 3 dashed dependency arrows. The Processor shows its two attributes and two methods. Each arrow points from Processor toward the class it depends on.

Arrows are solid instead of dashed?

If you drew a connector manually (by dragging from a directional arrow) instead of using the dependency connector from the UML library, it defaults to a solid line. Select the connector, open the Style tab in the format panel on the right, and change the Pattern from solid to dashed.

Also check the target arrowhead. In the Style tab, find the target arrow dropdown and select an open (unfilled) arrowhead. A filled triangle means inheritance, not dependency.

help me style my connector as a dashed dependency arrow in draw.io

Your Processor now has a concrete presence on the canvas, with clear dependencies on the data types it works with. Next up, you'll design the first strategy hierarchy that gives the Processor its swappable processing modes.

Design the Processing Mode Strategy

Your Processor class is on the canvas with its attributes and methods defined. Now it's time to design the architecture that gives those attributes real meaning.

The Processor needs to behave differently depending on its current mode. It could dump data, pass it through to a database, or validate before storing. Without a clean architecture, you'd end up with a giant if/else chain inside process() that grows every time you add a new mode. The Strategy pattern solves this by extracting each behavior into its own class behind a common interface.

In this step, get ready to:
  • Draw the ProcessingMode interface that defines how all modes behave.
  • Create three concrete mode classes (DumpMode, PassthroughMode, ValidateMode).
  • Connect the concrete classes to the interface with realization arrows.
Draw the ProcessingMode interface

An interface defines a contract that all concrete classes must follow. Every processing mode will implement this interface, guaranteeing the Processor can call any mode the same way.

  • Drag a class shape from the UML shape library in the left panel onto the canvas.
  • Double-click the class name section and type <<interface>> on the first line, then ProcessingMode on the line below it.
  • Leave the attributes section empty (interfaces don't hold state).
  • In the methods section, add: + execute(data: DataPoint, db: DatabaseConnection): void.

You should now see a new class shape on your canvas labeled ProcessingMode with the interface stereotype above it.

Why does execute() receive a database parameter?

PassthroughMode and ValidateMode both need to interact with a database. Instead of each mode holding its own database reference, the Processor passes its current database into execute() as a parameter.

This means the Processor is the single point of control for which database is active. DumpMode simply ignores the parameter.

Draw the three concrete mode classes

Each concrete class represents one specific behavior the Processor can execute. All three share the same method signature from the interface.

  • Drag a new class shape onto the canvas and set the class name to DumpMode.
  • Leave the attributes section empty.
  • In the methods section, add: + execute(data: DataPoint, db: DatabaseConnection): void.
  • Drag a second class shape and set the class name to PassthroughMode.
  • Add the same method: + execute(data: DataPoint, db: DatabaseConnection): void.
  • Drag a third class shape and set the class name to ValidateMode.
  • Add the same method: + execute(data: DataPoint, db: DatabaseConnection): void.

Your canvas now shows four new shapes: the ProcessingMode interface and three concrete classes beneath it.

What does each mode do?

  • DumpMode discards the data entirely. It ignores both the data and the database parameter.
  • PassthroughMode calls db.insert(data) to store the data without any checks.
  • ValidateMode calls db.validate(data) first, then db.insert(data) if validation passes.

Why is this better than if/else?

With the Strategy pattern, adding a fourth mode (like a "TransformMode") means creating one new class that implements ProcessingMode. You never touch the Processor class itself. This follows the Open/Closed Principle: open for extension, closed for modification.

Draw realization arrows from each mode to the interface

Realization arrows show that a class implements an interface. In UML notation, this is a dashed line with a hollow triangle pointing at the interface.

  • In the UML shape library, find the realization connector (dashed line with a hollow triangle).
  • Drag the connector onto the canvas, then attach one end to DumpMode and the hollow triangle end to ProcessingMode.
  • Draw a second realization arrow from PassthroughMode to ProcessingMode.
  • Draw a third realization arrow from ValidateMode to ProcessingMode.

Changing arrow style in the Style tab

If you draw a plain connector first, you can change it to a realization arrow afterwards. Select the connector, open the Style tab in the right panel, and change the source/target arrows from the drop-down list.

Before you review your canvas, predict: how many total class shapes should you see for the ProcessingMode hierarchy (including the interface itself)?

You should count 4 shapes in this hierarchy: the ProcessingMode interface plus DumpMode, PassthroughMode, and ValidateMode. Each concrete class connects to ProcessingMode with a dashed realization arrow (hollow triangle pointing at the interface). All three classes show the identical execute method signature.

Arrows pointing the wrong way?

The hollow triangle must point AT the interface (ProcessingMode), not at the concrete class. If your arrows point downward toward DumpMode, select each arrow and swap its direction by dragging the triangle end to ProcessingMode instead.

If your arrows appear as solid lines instead of dashed, select the arrow and check the Style tab in the right panel. Change the line style to dashed.

help me fix my realization arrows in draw.io

Your first strategy hierarchy is complete. Next up, you'll build the second strategy hierarchy for database connections, giving the Processor the ability to swap between Postgres, Redis, and Elastic at runtime.

Design the Database Connection Strategy

Your processing mode hierarchy is complete. Now you need to tackle the second axis of variation: databases.

Each database (Postgres, Redis, Elastic) requires a different implementation for insert and validate operations. Without a common interface, the processing modes would need to know which specific database they're talking to. The Strategy pattern lets you swap databases without the modes caring which one is active.

In this step, get ready to:
  • Draw the DatabaseConnection interface with its three method signatures.
  • Draw three concrete database classes that implement the interface.
  • Connect the concrete classes to the interface with realization arrows.
Draw the DatabaseConnection interface

Just like ProcessingMode defines a contract for all modes, you need an interface that defines what every database connection must be able to do. The Processor will depend on this abstraction instead of any specific database.

  • Drag a class shape from the left panel onto an empty area of your canvas, to the right of your ProcessingMode hierarchy.
  • Double-click the class name section and type DatabaseConnection.
  • Above the name, add the stereotype label <<interface>> to mark this as an interface.
  • Leave the attributes section empty. Interfaces don't hold state.
  • Double-click the methods section and add these three method signatures, one per line:
+ connect(): void
+ insert(data: DataPoint): void
+ validate(data: DataPoint): boolean

What do these methods represent?

These three methods define the full contract that any database must fulfill.

  • connect() establishes the connection to the database.
  • insert(data: DataPoint) stores a data point in the database.
  • validate(data: DataPoint) checks a data point against existing records and returns true or false.

You should now see a DatabaseConnection interface shape on your canvas with three methods listed and no attributes.

Shape doesn't have three sections?

Make sure you dragged a UML class shape from the UML shape library in the left panel. Regular rectangles don't have the three-section structure. If you used a plain shape, delete it and drag the correct UML class shape instead.

Help me fix my draw.io class shape so it has name, attributes, and methods sections.

Draw the three concrete database classes

Each concrete class implements the same three methods but with database-specific behavior. Postgres uses SQL queries, Redis uses key-value commands, and Elastic uses search indices.

  • Drag a new class shape below the DatabaseConnection interface.
  • Set the class name to PostgresConnection.
  • Leave the attributes section empty.
  • Add the following methods to the methods section:
+ connect(): void
+ insert(data: DataPoint): void
+ validate(data: DataPoint): boolean

You should see PostgresConnection on the canvas with all three methods matching the interface above it.

  • Drag another class shape and set its name to RedisConnection.
  • Leave attributes empty and add the same three methods:
+ connect(): void
+ insert(data: DataPoint): void
+ validate(data: DataPoint): boolean
  • Drag one more class shape and set its name to ElasticConnection.
  • Leave attributes empty and add the same three methods:
+ connect(): void
+ insert(data: DataPoint): void
+ validate(data: DataPoint): boolean

Why do all three classes have identical method signatures?

That's the whole point of the interface contract. Every class that implements DatabaseConnection promises it can do connect(), insert(), and validate(). The internal implementation differs, but the Processor never needs to know those details.

You should now see four new shapes on your canvas: the DatabaseConnection interface at the top and PostgresConnection, RedisConnection, and ElasticConnection below it.

Canvas getting crowded?

Position the entire DatabaseConnection group to the right of your ProcessingMode group. This keeps your two strategy hierarchies visually separate. You can select multiple shapes by dragging a selection box around them, then move them together.

Draw realization arrows from each database class to the interface

Realization arrows show that a class implements an interface. You used these same arrows to connect your mode classes to ProcessingMode in the previous step.

  • Draw a dashed line with a hollow triangle from PostgresConnection pointing to DatabaseConnection. The hollow triangle sits on the interface end.
  • Draw a second dashed line with a hollow triangle from RedisConnection pointing to DatabaseConnection.
  • Draw a third dashed line with a hollow triangle from ElasticConnection pointing to DatabaseConnection.

What does the realization arrow mean?

In UML, a dashed line with a hollow triangle represents "implements" in Java. It tells anyone reading the diagram that PostgresConnection, RedisConnection, and ElasticConnection all fulfill the DatabaseConnection contract.

Arrow looks solid instead of dashed?

A solid line with a hollow triangle is inheritance (extends), not realization (implements). Select the arrow and check the Style tab on the right panel. Change the line style to dashed. In draw.io, you can also right-click the connector and change its source/target arrows from the drop-down list.

How do I change a connector's line style to dashed in draw.io?

Before you move on, compare your DatabaseConnection hierarchy to the ProcessingMode hierarchy you built earlier. Do they follow the same structural pattern?

They should mirror each other: one interface at the top, three concrete implementations below, connected by dashed realization arrows with hollow triangles pointing at the interface. Both strategy hierarchies use the exact same UML notation.

✔️ Awesome, my hierarchies match!

Great. Your canvas now has two parallel strategy hierarchies. The Processor will depend on both of these interfaces, giving it the ability to swap modes and databases independently.

ⓧ I'd like to double check my diagram

Here is what you should have for the DatabaseConnection hierarchy specifically:

  • DatabaseConnection labeled <<interface>> with methods: + connect(): void, + insert(data: DataPoint): void, + validate(data: DataPoint): boolean.
  • PostgresConnection with the same three methods. No attributes.
  • RedisConnection with the same three methods. No attributes.
  • ElasticConnection with the same three methods. No attributes.
  • Three dashed realization arrows (hollow triangles) pointing from each concrete class up to the DatabaseConnection interface.

Your two strategy hierarchies are in place. Next up, you'll wire them both into the Processor with composition arrows, completing the architecture that makes the whole system dynamically reconfigurable.

Wire Composition Relationships and Export

Your database strategy hierarchy is complete, with three concrete connection classes implementing a single interface. Now it's time to wire everything together with composition arrows and produce a submission-ready export.

Right now, the Processor, mode hierarchy, and database hierarchy sit as separate clusters on your canvas. Composition arrows show that the Processor "owns" one ProcessingMode and one DatabaseConnection at a time. These arrows are what make the design dynamically reconfigurable.

In this step, get ready to:
  • Draw composition arrows from the Processor to each strategy interface.
  • Arrange the diagram for readability.
  • Export the completed diagram as a PDF.
Draw composition arrows from Processor to each interface

In UML, a composition relationship means the "whole" owns the "part" and the part cannot exist without the whole. The filled diamond always sits on the owning class.

  • In the left panel, find the composition connector in the UML shape library. It is a solid line with a solid (filled) diamond at one end.
  • Drag or draw the composition connector from Processor to ProcessingMode. Make sure the filled diamond end sits on the Processor (it "owns" the mode).
  • Double-click on the connector near the ProcessingMode end to add a label.
  • Type 1 and press Enter to save. This multiplicity label shows the Processor holds exactly one mode at a time.
  • If the label isn't positioned well, click it and drag the small yellow diamond handle to reposition it closer to the ProcessingMode end.

You should see a solid line with a filled black diamond on the Processor end, connecting to ProcessingMode, with a "1" label near the interface.

  • Repeat the same process: draw a composition connector from Processor to DatabaseConnection, with the filled diamond on the Processor end.
  • Double-click on the connector near the DatabaseConnection end and type 1 as the multiplicity label.

You should now see two composition arrows fanning out from the Processor, each with a filled diamond on the Processor end and a "1" label near the target interface.

What do these composition arrows mean?

The filled diamond indicates that the Processor controls the lifecycle of its strategy objects. If the Processor is destroyed, its current mode and database references serve no purpose.

The "1" multiplicity means the Processor holds exactly one of each at any time. The Processor's behavior is entirely determined by whichever concrete strategy objects are currently plugged in.

Why composition instead of aggregation?

Aggregation (open diamond) means the part can exist independently. Composition (filled diamond) means the part cannot exist without the whole. Here, the strategy objects are created and owned by the Processor's configure() method. They have no purpose outside of it.

Diamond on the wrong end?

The filled diamond must sit on the Processor, not on the interface. If yours is reversed, right-click the connector and look for an option to reverse the direction. Alternatively, delete the connector and redraw it starting from the Processor class.

help me fix the direction of my composition arrow in draw.io

Arrange the diagram for readability

A well-laid-out diagram communicates structure at a glance. Your reviewer should see the Processor at the top with the two strategy hierarchies branching below it.

  • Drag the Processor class to the center-top area of the canvas.
  • Place the three given classes (DataPoint, ModeIdentifier, DatabaseIdentifier) to the upper-right or upper-left of the Processor.
  • Place the ProcessingMode interface below the Processor on the left, with its three implementations (DumpMode, PassthroughMode, ValidateMode) arranged below it.
  • Place the DatabaseConnection interface below the Processor on the right, with its three implementations (PostgresConnection, RedisConnection, ElasticConnection) arranged below it.
  • Adjust positions so that arrows do not cross unnecessarily. If a connector overlaps another shape, drag the connected classes apart to give the arrows more room.

Your diagram should now read top-to-bottom: Processor at the top composing two interfaces in the middle, with concrete implementations fanning out at the bottom.

Snap to grid for alignment

If your shapes feel misaligned, draw.io snaps to a grid by default. Hold shapes by their center and drag slowly to let them snap into even rows and columns.

Export the diagram as PDF

With your diagram complete and arranged, export it as a submission-ready PDF.

  • Click File in the top menu bar.
  • Select Export as, then click PDF.
  • In the export dialog, enable the Crop option to fit the PDF to your diagram size.
  • Click Export and save the file to your device.

Before you open the PDF, think about what you expect to see. How many total relationship arrows should the diagram contain?

  • Open the exported PDF on your device to confirm everything rendered correctly.

You should see 11 total relationship arrows: 3 dashed dependency arrows from Processor to the given classes, 2 solid composition arrows (filled diamond) from Processor to the interfaces with "1" labels, 3 dashed realization arrows to ProcessingMode, and 3 dashed realization arrows to DatabaseConnection. All class names, attributes, and methods should be readable.

PDF looks blank or cut off?

Make sure you enabled the Crop option before exporting. Without it, the PDF may include a large empty area around your diagram. If shapes are cut off, some elements may be positioned far from the main group. Drag any outlying shapes closer and re-export.

help me fix my draw.io PDF export

Secret mission

Add a ProcessorFactory

Right now, your Processor's configure() method hides a switch statement that maps enums to concrete classes. That violates the Open/Closed Principle. Extract the creation logic into a dedicated Factory class that keeps your Processor clean and makes adding new strategies a one-line change.

Clean Up Your Resources

Clean Up Your Resources

This project runs entirely in your browser and saves files locally to your device. There are no ongoing costs or cloud resources to worry about.

Resources you used:

  • DataProcessorArchitecture diagram file (saved locally on your device).
  • DataProcessorArchitecture.pdf export (saved locally on your device).

Decide whether to keep your files for future reference or delete them entirely.

Keep everything running

No action needed. Choose this if you want to revisit or extend your diagram later.

  • Your diagram file stays wherever you saved it on your device.
  • You can reopen it anytime at app.diagrams.net by selecting File > Open from > Device.
  • draw.io is browser-based, so nothing is installed on your machine.

Pause - I'll come back to this later

Since this project is entirely local files, pausing is the same as keeping. Your files sit on your device until you come back.

  • Close the draw.io browser tab.
  • Your saved diagram file and PDF remain on your device for whenever you return.

Delete - I don't want to use this again

Remove all project files from your device to start fresh.

  • Close the draw.io browser tab.
  • Navigate to the folder where you saved your diagram file and PDF.
  • Delete the DataProcessorArchitecture diagram file (.drawio or .xml format).
  • Delete the DataProcessorArchitecture.pdf file.
  • Empty your Recycle Bin (Windows) to permanently remove the files.

Nice Work!

Nice Work!

You just designed a complete UML class diagram for a dynamically reconfigurable data processor using the Strategy pattern. This is the kind of architecture diagram that proves you can think in abstractions, not just code.

You've learned how to:

  • Applied the Strategy pattern twice to decouple processing modes and database connections from the Processor, making both axes of variation independently swappable at runtime.
  • Used proper UML notation for realization (dashed line, hollow triangle), composition (solid line, filled diamond), and dependency (dashed line, open arrow) to communicate architecture decisions visually.
  • Demonstrated SOLID principles in practice. Your design follows the Open/Closed Principle (add new modes or databases without changing the Processor), Single Responsibility (each class does one thing), and Dependency Inversion (Processor depends on abstractions, not concretions).
  • Secret Mission: Added a Factory pattern to further separate concerns and eliminate switch-statement logic from the Processor.

Ready to quiz yourself?