25T1 Week 9
Thursday 9am-12pm (H09B)
Slides by Sam Zheng (z5418112)
Original slides by Alvin Cherk
Finding patterns
In groups, determine a possible pattern that could be used to solve each of the following problems:
Strategy
Composite
Iterator
Observer
Command
Decorator
Template
Code and Design Smells
Mark, Bill and Jeff are working on a PetShop application. The PetShop has functionality to feed, clean and exercise different types of animals.
Mark notices that each time he adds a new species of animal to his system, he also has to rewrite all the methods in the PetShop so it can take care of the new animal.
What code or design smell is present here?
public class Person {
private String firstName;
private String lastName;
private int age;
private int birthDay;
private int birthMonth;
private int birthYear;
private String streetAddress;
private String suburb;
private String city;
private String country;
private int postcode;
public Person(String firstName, String lastName,
int age, int birthDay, int birthMonth,
int birthYear, String streetAddress,
String suburb, String city, String country,
int postcode) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.birthDay = birthDay;
this.birthMonth = birthMonth;
this.birthYear = birthYear;
this.streetAddress = streetAddress;
this.suburb = suburb;
this.city = city;
this.country = country;
this.postcode = postcode;
}
// Some various methods below...
}
What code or design smell is present here?
Data clumps & long parameter list
How would you refactor to fix this?
If some of the input was "optional" builder pattern may be useful here
public class MathLibrary {
List<Book> books;
int sumTitles {
int total = 0
for (Book b : books) {
total += b.title.titleLength;
}
return total;
}
}
public class Book {
Title title; // Our system just models books
// as titles (content doesn't matter)
}
public class Title {
int titleLength;
int getTitleLength() {
return titleLength;
}
void setTitleLength(int tL) {
titleLength = tL;
}
}
What code or design smell is present here?
How would you refactor to fix this?
How do these code smells cause problems when developing code?
How fast does it take for a new developer to understand what is happening? Is behaviour predictable, reasonable and uniform?
Is a code smell always emblematic of a design problem?
No
What kind of design pattern is it?
Behavioural
// Base class for shapes
abstract class Shape {
abstract void draw();
abstract double calculateArea();
}
class Circle extends Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
void draw() {
System.out.println("Drawing a circle with radius " + radius);
}
@Override
double calculateArea() {
return Math.PI * radius * radius;
}
}
class Rectangle extends Shape {
private double width;
private double height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
@Override
void draw() {
System.out.println("Drawing rectangle, w:" + width + " h: " + height);
}
@Override
double calculateArea() {
return width * height;
}
}
// Client code
public class Main {
public static void main(String[] args) {
Shape[] shapes = {new Circle(5), new Rectangle(4, 6)};
for (Shape shape : shapes) {
shape.draw();
System.out.println("Area: " + shape.calculateArea());
}
}
}interface Shape {
void accept(ShapeVisitor visitor);
}
class Circle implements Shape {
double radius;
Circle(double radius) { this.radius = radius; }
@Override
public void accept(ShapeVisitor visitor) { visitor.visit(this); }
}
class Rectangle implements Shape {
double width, height;
Rectangle(double w, double h) { this.width = w; this.height = h; }
@Override
public void accept(ShapeVisitor visitor) { visitor.visit(this); }
}
interface ShapeVisitor {
void visit(Circle circle);
void visit(Rectangle rectangle);
}
class DrawVisitor implements ShapeVisitor {
@Override public void visit(Circle c) { System.out.println("Draw Circle: " + c.radius); }
@Override public void visit(Rectangle r) { System.out.println("Draw Rect: " + r.width + "x" + r.height); }
}
public class Main {
public static void main(String[] args) {
Shape[] shapes = {new Circle(5), new Rectangle(4, 6)};
ShapeVisitor draw = new DrawVisitor();
for (Shape shape : shapes) shape.accept(draw);
}
}Computers
In this scenario we have Computers, Keyboards and Mouses which all are of type ComputerComponent. We want to be able to 'visit' different types of Computer components by logging the following messages:
Looking at computer Corelli with memory 500 GB.
Looking at keyboard Mechanical keyboard which has 36 keys.
Looking at mouse Bluetooth mouse.
In particular though, anyone which is visiting a Computer must be validated prior to being able to visit.
Extend/modify the starter code to use the Visitor Pattern to allow different computer components to be visited.