The following are topics that are no longer in the course and NOT examinable but if you were interested, you are free to check out!
* Not examinable
What is it?
Behavioural design pattern that allows an object to alter its behaviour when its internal state changes.
When should we use this pattern?
Player has methods that can change its statePlayer changes based on its state
PlayingState ReadyStateLockedStateFind out more at State (refactoring.guru)
* Not examinable
How can I add functionalities to legacy systems without altering the existing codebase too much?
The Visitor pattern suggests that you place the behaviour into a separate class, instead of trying to integrate it into existing classes
What is it?
Behavioural design pattern that allow algorithms and objects that the algorithms operate on to be separated
Benefits
When to use?
New operations need to be added to all elements of an existing object structure
Element classes must have an accept function that invokes the visit function of the Visitor
Visitor interface declares a set of visiting methods * Not examinable
What is this?
Behavioural design pattern that defines the skeleton of an algorithm in the superclass but lets subclasses override specific steps without changing its structure.
Why use it?
Let clients extend only particular steps of an algorithm, but not the whole structure
What does it fix?
When you have several classes that contain almost identical algorithms with some minor differences.
AbstractClass: Declares methods that act as steps of an algorithm, and the templateMethod() which calls these methods in a specific order
ConcreteClass: Can override all the steps, but not the template method itselfpublic abstract class AbstractClass {
// Template Method
public final void executeAlgorithm() {
step1();
step2();
step3();
}
// Abstract steps to be implemented by subclasses
public abstract void step1();
public abstract void step2();
public abstract void step3();
}Abstract Class
Concrete Class
public class ConcreteClass extends AbstractClass {
@Override
protected void step1() {
// Custom implementation for step 1
}
@Override
protected void step2() {
// Custom implementation for step 2
}
@Override
protected void step3() {
// Custom implementation for step 3
}
}In a cafe, we have the task of crafting different beverages. Each type of beverage such as coffee, tea and milk tea follow a similar structure but differ in behaviour at each step.
For example all beverages have the structure:
Use the template pattern to refactor this code.
* Not examinable
What is this?
Structural design pattern that allows objects with incompatible interfaces to collaborate.
Why use it?
Often used to make existing classes (APIs) work with a client class without modifying their source code
What does it fix?
E.g. You have a legacy system that uses one type of interface and a new system that uses another.
Adapter is able to work with the client and the service.
ClientInterface describes a protocol that other classes must follow to be able to collaborate with the Client
We have a scenario involving round holes and blocks, and square blocks that need to be adapted to fit into round holes.
Our task is to implement the Adapter Pattern to allow square blocks to be used with round holes.
* Not examinable
What is it?
Creational design pattern that lets you construct complex objects step by step.
Allows us to produce different types and representations of an object using the same construction process
Benefits
When to use?
Use to get rid of "telescoping constructor"
Say we have a monstrous constructor...
Car car = new Car(id, brand, null, color,
nbrDoors, null, weight, null);What happens if we don't require all the fields for this class?
When to use?
Use to get rid of "telescoping constructor"
Say we have a monstrous constructor...
new Car(id, brand, model);
new Car(id, screenType, weight, height);
new Car(id, brand, model, color, nbrDoors);
new Car(id, brand, screenType, weight, height);A solution is to create several overloaded constructors, but now we have too many constructors
Builder Pattern suggests to extract the object construction or creation out of its own class and move it to separate classes called builders.
How could you extend this solution to add ToyTrains and a ToyTrainBuilder to the system?
This would require a builder interface and separate concrete builders, similar to the lecture examples
How could you extend this solution to add ToyTrains and a ToyTrainBuilder to the system?
TrainBuilder
ToyTrain
Builder
What we coded up was a relatively simple version of the Builder Pattern.
Going back to our cars, what happens if we find that for similar cars we are always reusing the same steps to construct the car?
Car car = new CarBuilder()
.id (2122)
.brand("Bugatti")
.model("Chiron")
.color("Blue")
.nbrDoors(2)
.engine("8L")
.height(115)
.build();Car car = new CarBuilder()
.id (2123)
.brand("Bugatti")
.model("Divo")
.color("Blue")
.nbrDoors(2)
.engine("8L")
.height(115)
.build();Car car = new CarBuilder()
.id (2123)
.brand("Bugatti")
.model("Divo")
.color("Black")
.nbrDoors(2)
.engine("8L")
.height(115)
.build();Introducing the Director which defines the order in which we should call the construction steps so that we can reuse specific configurations of the products we are building.
public class Director {
public void buildBugatti (CarBuilder builder) {
builder.brand("Bugatti")
.color("Blue")
.nbrDoors (2)
.engine ("8L")
.height(115);
}* Not examinable
class IntegerBox {
private Integer value;
public void shoutValue(Integer value) {
System.out.println(value.toString().toUpperCase + "!");
}
}class StringBox {
private String value;
public void shoutValue() {
System.out.println(value.toString().toUpperCase + "!");
}
}IntegerBox
StringBox
What are some design problems with this code?
What is it?
Style of programming that allow types to be used as a parameter to methods, classes and interfaces.
Why would you use it?
public class Box<T> {
private T value;
public Box(T value) {
this.value = value;
}
public void setValue(T value) {
this.value = value;
}
public T getValue() {
return value;
}
}
public class Box<T, S> {
private T value1;
private S value2;
public Box(T value1, S value2) {
this.value1 = value1;
this.value2 = value2;
}
public void setValue(T value1, S value2) {
this.value1 = value1;
this.value2 = value2;
}
public T getValue1() {
return value1;
}
public S getValue2() {
return value2;
}
}
Inside src/stack, there are a series of stubs for a Stack class which takes in a generic type. There are a series of tests inside StackTest.java which currently fail.
Implement the methods so that the tests pass, using an ArrayList to store the internal data structure.
Iterable
Iterable are objects that can be iterated over. Iterator
public interface Iterator<T> {
boolean hasNext();
T next();
void remove();
}Iterator
public interface Iterable<T> {
Iterator<T> iterator();
}public interface Iterator<T> {
boolean hasNext();
T next();
void remove();
}hasNext(): Returns true if iteration has more elements afternext(): Returns next element of iterationremove(): Removes from the collection the last element return by the iteratorpublic static Integer sumStack(Stack<? extends Integer> stack);
<? extends Type> and <? super Type> mean??? is called a wildcard and represents an unknown type. Provides flexibility for methods that accept a range of typesLet's say T = Fruit.
Then for List<? extends Fruit>, we can read any object in list that is fruit subclass (Strawberry, Banana) and treat it like Fruit
List<? extends T> src
List<? super T> dest
Say T = Strawberry.
? super Strawberry = Any container that can accept strawberries: a BerryBasket, a FruitBasket, or an ObjectBox.
You cannot add strawberries to a List<WildStrawberry> — that’s more specific, not general enough.