CPSC 210
D4: Composite Pattern
Slides designed by Felix Grund, based on Paul Carter’s slides
Learning Goals
- Understand why we want to use design patterns and where they come from
- To apply the Composite Design Pattern to a given problem
We make mistakes
We identify our mistakes
We learn from our mistakes
We prevent mistakes
We Evolve Design Patterns
Lessons Learned!
Why Design Patterns?
What is a design pattern?
"General, reusable solution to a commonly occurring problem within a given context in software design"
"Guidelines for software design that help you avoid mistakes that others repeatedly made in the past"
Other
definition:
What is a design pattern?
- a re-usable approach to solving a design problem
What is NOT design pattern?
- a re-usable library (e.g. Swing) or a reusable piece of code (e.g. ArrayList or HashSet)
What's the challenge?
- to adopt or adapt a design pattern for one's use case
- to decide whether a design pattern makes sense for a use case
The Composite Pattern
Products and Boxes
- Two types of objects: Products and Boxes
- Boxes can contain a product or other boxes
- How to determine the price of an order?
- Unwrap all the boxes
- Recursively go over all the products
- Calculate the total
- This is not simple in a program!
- What are the classes of products?
- What is the nesting level?
- A naive approach will either be painful or even impossible!
- Work with Products and Boxes through a common interface
- Interface declares a method for calculating the total price
Products and Boxes (2)
Product receipt = new Product("Receipt", 0.0);
Product hammer = new Product("Hammer", 20.00);
Product phone = new Product("Phone", 500.00);
Product headphones = new Product("Headphones", 50.00);
Product charger = new Product("Charger", 35.00);
Box toolBox = new Box("Tool Box");
toolBox.addItem(hammer);
Box techBox = new Box("Tech Box");
techBox.addItem(phone);
techBox.addItem(headphones);
Box chargerBox = new Box("Charger Box");
chargerBox.addItem(charger);
Box electronicsBox = new Box("Electronics Box");
electronicsBox.addItem(techBox);
electronicsBox.addItem(chargerBox);
Box orderBox = new Box("Order Box");
orderBox.addItem(toolBox);
orderBox.addItem(electronicsBox);
orderBox.addItem(receipt);
double price = orderBox.getPrice();
System.out.println("TOTAL PRICE: " + price);
Products & Boxes - Main Method
public abstract class Item {
protected String name;
public Item(String name) {
this.name = name;
}
abstract double getPrice();
}
Composite Implementation
Component
public class Box extends Item {
private List<Item> items;
public Box(String name) {
super(name);
this.items = new ArrayList<>();
}
public void addItem(Item item) {
this.items.add(item);
}
public double getPrice() {
double sum = 0;
for (Item item : items) {
sum += item.getPrice();
}
return sum;
}
}
Composite
public class Product extends Item {
private double price;
public Product(String name, double price) {
super(name);
this.price = price;
}
public double getPrice() {
return price;
}
}
Leaf
Composite: Motivation
I have a tree structure and I don't know all the types of objects in the tree.
I want to run some operations recursively through my tree without knowing the exact types in my tree.
Composite Pattern
Composite node: arbitrarily many children
Leaf node:
no children
When should I (not) use it?
- You want to implement a tree-like structure
- You have common functionality for all components in a tree
- Sometimes it's hard to find a common interface for components
- Components might sometimes not be "common enough" (overgeneralizing)
How to use it?
-
Identify your tree structure
- composite objects and leaf objects
- if you don't have such a structure, this pattern makes no sense!
- Introduce abstract type that captures common behaviours of both:
- Composite objects
- Leaf objects
Composite Class Diagram
In other words
Lecture Ticket
- You have branches and leaves.
- Branches can have offshoots of either branches or leaves.
- Leaves, obviously, cannot have any offshoots.
- You choose to model this in Object Orientation using the Composite Pattern.
- You identify three classes: Branch, Leaf and the third class, Offshoot.
Lecture Ticket - Part 1
What hierarchical relationship do these classes have to one another?
- Leaf extends Offshoot
- Branch extends Offshoot
- Offshoot extends nothing
We identify Offshoot as the component, Branch as the composite, and Leaf as the the leaf
Lecture Ticket - Part 2
Which of the following fields would exist in Offshoot, Branch and Leaf?
- Branch has a list of Offshoot
The aggregation from Branch to Offshoot would be implemented by adding a field of type List<Offshoot> to the Branch class.
Lecture Ticket - Part 3
Imagine that you want to change the color of all the leaves to red. You want to do this by adding a changeColor(Color) method. Where might the method be specified but not implemented?
The changeColor(Color) method is one that we would want to call on both a Leaf (to change the color of that individual leaf) and on a Branch (to change the color of all the leaves attached to that branch). This is therefore common behaviour that we want all offshoots (whether they be a branch or a leaf) to support. The method is therefore specified in the Offshoot class.
Lecture Ticket - Part 4
Where would the changeColor method be implemented?
- In Branch, where it has a for-loop that iterates over its entire internal collection recursively invoking changeColor(Color) on each element
- In Leaf, where it changes the field that holds the color
Lecture Lab
Lecture Lab Class Diagram
Let's make it prettier
tree changing color to RED
--b3 changing color to RED
----b2 changing color to RED
------l3 changing color to RED
----l4 changing color to RED
--b1 changing color to RED
----l1 changing color to RED
----l2 changing color to RED
Let's add indentation:
CPSC 210
D4: Composite Pattern
Composite Class Diagram
Lecture Lab #2
Lecture Lab #2
Lecture Lab Class Diagram
Folder
File
FileSystemResource
addChild(...)
print()
Lecture Lab Class Diagram
Folder
File
FileSystemResource
addChild(...)
print()
D4: Composite Pattern
The End - Thank You!
D4: Composite
By firas_moosvi
D4: Composite
- 102