Introduction to Object-Oriented

[email protected] – 2016 Sorting 1: String Sorting 2 jonkv@ida

First: An illustrating problem

 Suppose you need to sort some strings

Implement sorting algorithms public class StringSorter { public void quicksort(String[] strings) { … } public void mergesort(String[] strings) { … } }

Use the algorithms String[] strings = new String[numberOfStrings]; … StringSorter mySorter = new StringSorter(); mySorter.quicksort(strings); Sorting 2: String Comparisons 3 jonkv@ida

 A sorting algorithm must be able to compare two elements Obvious: Comparison inside the sort method public class StringSorter { public void quicksort(String[] array) { … // Should element #i be before element #j? if (array[i].compareTo(array[j]) < 0) { … } } } String has a built-in compareTo method

Returns -1, 0 or 1: str1 should be before, equal to, or after str2 Sorting 3: Different Sort Orders 4 jonkv@ida

 And sometimes you need an inverse sort order Obvious solution: Add a flag public class StringSorter { private boolean inverseOrder; public StringSorter(boolean inverse) { this.inverseOrder = inverse; }

public void quicksort(String[] strings) { … // Should element #i be before element #j? if ( !inverseOrder && array[i].compareTo(array[j]) < 0 || inverseOrder && array[i].compareTo(array[j]) > 0) { … } } Different comparisons } depending on standard or inverse order Sorting 4: Additional Sort Orders 5 jonkv@ida

 You sometimes use different locales . Danish: …xyzäöå . Swedish: …xyzåäö . English: aåäbcde… . Add a locale specifier to the StringSorter

 Someone wants to sort strings representing dates . In day/month/year format . Add a new flag indicating date sorting should be used

 … Sorting 5: Lack of Flexibility 6 jonkv@ida

 So what’s the problem?

Every time we want a new sorting criterion, the sort method must be changed  can't be in a class library

Having many sorting criteria leads to long and complex conditional tests

A pure sorting algorithm should not have knowledge about the type of data being sorted

Inflexible!

Callbacks using Higher-Order Functions 8 jonkv@ida

 One general approach: Higher-order functions Python example from TDDD73 def combine(func,seq): Takes another function result = seq[0] as parameter for element in seq[1:]: result = func(result,element) return result

String sorting example

void quicksort(String[] strings, function compare) { Takes a comparison function … as a parameter // Should element #i be before element #j? if (compare(strings[i], strings[j]) < 0) { … Call this callback function } to determine element order! } Many OO languages do not support this! How do we find a pure OO solution? Callbacks using Objects 9 jonkv@ida

 OO approach: Let an object compare the elements for us

public interface StringComparator { Returns -1, 0 or 1: str1 should be int compare(String str1, String str2); before, equal to, or after str2 }

public class StringSorter { private final StringComparator comp; public StringSorter(StringComparator comp) { this.comp = comp; } Specify a comparator public void quicksort(String[] strings) { when the sorter is created … // Should element #i be before element #j? if (comp.compare(strings[i], strings[j]) < 0) { … } } } Call the specified comparator's method

This is an object-oriented way of implementing callbacks! Implementing Comparators 10 jonkv@ida

 Now you can implement as many comparators as needed! . No need to change the StringSorter – reuse it for arbitrary sort orders public class LengthComparator implements StringComparator { public int compare(String str1, String str2) { int len1 = str1.length(); int len2 = str2.length(); if (len1 > len2) return 1; else if (len1 < len2) return -1; else return 0; } } Using Comparators 11 jonkv@ida

StringComparator lengthcomp= new LengthComparator(); StringSorter sorter = new StringSorter(lengthcomp); sorter.quicksort(strings);

sorter … comp.compare() …

StringSorter class Object The sorter (data) sort() [code] is told which header: … [code] comparator comp … [code] to use … … LengthComparator class Object The comparator (data) compare() [code] may have no fields / data, header: … [code] but it has methods … [code] that the sorter can call Java Collections Framework: Comparator 12 jonkv@ida

 The Collections Framework has a generic comparator interface

public interface Comparator { int compare(T obj1, T obj2); }

public class Sorter { private final Comparator comp;

public Sorter(Comparator comp) { this.comp = comp; }

public void quicksort(List list) { // ... // Should element #i be before element #j? if (comp.compare(list.get(i), list.get(j)) < 0) { /* ... */} } } Also, built-in sort method: Collections.sort(students, new NameLengthComparator());

Generalization 1: Similar Problems 14 jonkv@ida

 Similar problems and solutions arise in many places . Any JComponent in the Java GUI can have a border ▪ Not a built-in repertoire of borders ▪ Instead, callback objects implementing the Border interface ▪ Change border: component.setBorder(Border b) ▪ Can easily define a new Border, with arbitrary design Generalization 2: Similar Problems 15 jonkv@ida

. Any Container in the Java GUI can lay out its subcomponents ▪ Set a layout callback object using component.setLayout() ▪ Uses a LayoutManager interface with concrete managers FlowLayout, BorderLayout, … ▪ Can easily define a new LayoutManager

. A text component might need input validation ▪ JTextField supports an InputVerifier interface ▪ You can provide Numeric, AlphaNumeric, TelNumber verifier classes

. … Generalization 3: A Pattern 16 jonkv@ida

 There is a certain pattern in the design of these classes!

Class General interface that needs to be parameterized for parametrization

StringSorter – which sort order? StringSorter – StringComparator JComponent – which border? JComponent – Border Container – which layout? Container – LayoutManager JTextField – which input pattern? JTextField – InputVerifier

This parametrization requires Concrete Concrete implementation code, not just values! Concrete implementation Concrete implementation implementation

Strategy pattern: A comparator object specifies which comparison strategy to use, a border object specifies which border painting strategy to use, … One Use of Strategy: String Sorting 17 jonkv@ida

. StringSorter + Comparator shows one way of using a Strategy StringComparator StringSorter <> comp: Comparator ”Arrow with diamond” quicksort(String[] array) compare(String first, means aggregation: mergesort(String[] array) String second) Any StringSorter has a Comparator

DefaultOrder InverseOrder DateOrder

compare(String first, compare(String first, compare(String first, String second) String second) String second)

Separation of concerns: StringSorter knows nothing about specific sort orders One Use of Strategy: Border Drawing 18 jonkv@ida

. JComponent + Border shows another way of using a Strategy

JComponent Border <> bord: Border paint() paintBorder(Graphics g)

LineBorder EtchedBorder ThickBorder

paintBorder(Graphics g) paintBorder(Graphics g) paintBorder(Graphics g)

Separation of concerns: JComponent knows nothing about specific border types The General 19 jonkv@ida

 We can lift out a general design pattern that can be reused! Context Strategy<> Standardized terminology for this pattern type: ContextInterface() AlgorithmInterface() Context, Strategy, ConcreteStrategyX

ConcreteStrategyA ConcreteStrategyB

AlgorithmInterface() AlgorithmInterface()

Patterns – in general 21 jonkv@ida

 "Pattern" has many meanings . Some relevant in this context:

▪ 5. a combination of qualities, acts, tendencies, etc., forming a consistent or characteristic arrangement – Dictionary.com

▪ 10: a discernible coherent system based on the intended interrelationship of component parts – Merriam-Webster Design Patterns 22 jonkv@ida

 Originates in architecture! . et al. (1977) state that a pattern: ▪ describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice. Design Patterns and Classes 23 jonkv@ida

 Object-oriented design patterns: . How do we arrange our classes to solve a particular type of problem? ▪ Which interfaces and classes to create? ▪ Who knows about whom? ▪ Who inherits from whom? ▪ How do they call each other? ▪ … Creational Structural Behavioral Abstract factory Adapter Chain of responsibility Builder Bridge Command Factory method Composite Interpreter Prototype Decorator Iterator Singleton Facade Mediator Flyweight Memento Proxy Observer State Strategy Template Visitor Object-Oriented Design Patterns 24 jonkv@ida

 A typical object-oriented design pattern: . Describes a general way of organizing your classes, objects, methods to solve a kind of problem

Context Strategy<>

ContextInterface() AlgorithmInterface()

ConcreteStrategyA ConcreteStrategyB

AlgorithmInterface() AlgorithmInterface()

. Can be quite different from how the problem would be solved in a non-OO language Object-Oriented Design Patterns (2) 25 jonkv@ida

 A typical object-oriented design pattern: . Can be quite different from void how the problem would be quicksort(String[] strings, function compare) { solved in a non-OO language … // Should element #i be before element #j? if (compare(strings[i], strings[j]) < 0) { … } }

. Gives you a repertoire of techniques that you might not have thought of on your own

. Has been refined to provide flexibility that the first solution you think of might lack – take advantage of others' experience! Object-Oriented Design Patterns (3) 26 jonkv@ida

 A typical object-oriented design pattern: . Provides a common vocabulary to talk about solutions

Context Strategy<>

ContextInterface() AlgorithmInterface()

ConcreteStrategyA ConcreteStrategyB

AlgorithmInterface() AlgorithmInterface()

. Makes it easier to read existing code, because you know the pattern

. Generally can’t be completely implemented in a class library ▪ Different methods needed, different parameters, … – no single solution! Object-Oriented Design Patterns (4) 27 jonkv@ida

 Object-oriented patterns are ”mined”! . Only recognized as patterns when we see similar solutions reused again and again

 Many useful patterns have been found . Should be aware of them . Helps you find solutions to complex problems . Helps you avoid solutions that are inflexible, difficult to maintain

But don’t use them blindly! Often introduce some additional complexity: New classes, new levels of indirection (method calls to Comparator), …

Sometimes worth the complexity, sometimes not!

Delegation 29 jonkv@ida

 Strategy builds on delegation . Passing part of your responsibilities to someone else StringSorter StringComparator <> comp: Comparator quicksort(String[] array) compare(String first, String second) mergesort(String[] array)

I need to check the order Let some Comparator do it! between two strings…

public void quicksort(String[] array) { … // Should element #i be before element #j? // Let’s delegate the question! if (comp.compare(array[i], array[j]) < 0) { … } … } Delegation (2) 30 jonkv@ida

 Some consider delegation to be a design pattern . But it is very abstract . The original book says: It is a technique with which many patterns are implemented

Spreadsheet Problem 1 32 jonkv@ida

 Consider a spreadsheet . Edit a value, press enter ▪  Call commitValue(Cell c, Value v) ▪  Must recalculate dependent values

 Initial solution: . Just let commitValue() call recalculate() Spreadsheet Problem 2 33 jonkv@ida

 Weaknesses in the initial solution: Why should commitValue . You have to update the screen as well explicitly know about these functions? ▪ Hard-code another call Violates the Single . A graph may be dependent on this value Responsibility Principle! ▪ Let commitValue() know about graphs For every new functionality interested in value changes you will have to change commitValue()! Spreadsheet Problem 3 34 jonkv@ida

 Solution, once again: Callback objects public interface ChangeObserver { Interface for anyone void notifyCellChanged(Cell c); interested in changes } public class Recalculator public class ScreenUpdater implements ChangeObserver implements ChangeObserver { { public void notifyCellChanged(Cell c) { public void notifyCellChanged(Cell c) { // … recalculate dependent values … // … update the screen … } } } } Spreadsheet Problem 4 35 jonkv@ida public interface ChangeObserver { void notifyCellChanged(Cell c); Has a list of interested ChangeObservers } Has no idea there are Recalculators, ScreenUpdaters, GraphUpdaters, … public class SpreadsheetPage {  Fewer dependencies, more modular! private List observers; public void addChangeObserver(ChangeObserver obs) { observers.add(obs); }

public void commitValue(Cell c, Value v) { // … make all internal changes … Makes a change, notifyAllObservers(c); then calls notification }

public void notifyAllObservers(Cell c) { for (ChangeObserver obs : observers) { obs.notifyCellChanged(c); } } } Spreadsheet Problem 5 36 jonkv@ida

 To use: SpreadsheetPage page = new SpreadsheetPage(); page.addChangeObserver(new Recalculator()); page.addChangeObserver(new ScreenUpdater());

 Similar situations: . Word processor ▪ Modified: Text document ▪ Interested: Spell checker + word counter + text window

. Web browser ▪ Modified: Bookmark list ▪ Interested: Multiple windows, each showing bookmarks Extracting a Pattern 37 jonkv@ida

 Is there a pattern?

Observable Observer Object whose state changes: Objects interested in the change: Spreadsheet, Screen updater, Document, Spell checker, Bookmark list Word counter

Each observable keeps track of All interested classes a set of interested classes: implement an interface: List, ChangeObserver, … addChangeObserver(), …

When there is a change, The source of the call a method does not have to know in every registered observer who will react or how! Observer Pattern 38 jonkv@ida

 Observer pattern Called Subject or Observable SpreadsheetPage

ChangeObserver +notifyCellChanged

The Subject class only knows about the general Observer! Recalculator GraphUpdater +notifyCellChanged +notifyCellChanged These classes are not known to Subject  looser coupling Observer Pattern 2 39 jonkv@ida

Again: Similar class diagram Again: Different usage Call methods in a class Call methods in any number of observers where the caller is only aware of the interface Not delegation: The observers are not helping the observable achieve its task but are interested for their own sake

Game Problem 1 41 jonkv@ida

 Example: Game with multiple "modes" per player public enum PlayerMode { NORMAL, // Standard mode STRONGER, // Stronger and less vulnerable FASTER, // Runs faster GHOST, … // Can walk, run or jump through solid matter } public class Player { Many methods affected private PlayerMode mode; by each power-up public void jump() { if (mode == PlayerMode.NORMAL) { Long conditional statements // Ordinary jump } else if (mode == PlayerMode.STRONGER) { // Jump a bit higher } else if (mode == PlayerMode.GHOST) { New powerups? Many methods // Can jump through platforms from to change – in Player! // below, land on platforms from above } … Not flexible + } not good separation of concerns Game Problem 2 42 jonkv@ida

 Use plain inheritance?

NormalPlayer General player code in NormalPlayer

GhostPlayer StrongPlayer FastPlayer Inherit standard behavior, override

Must replace the player (object) every time he gets a powerup!

We want one player, whose behavior changes! Game Problem 3 43 jonkv@ida

 Plug in a behavior mode? public interface PowerupState { Contains what public void jump(Player p); differs between powerup modes } public class NormalState implements PowerupState { public void jump(Player p) { // Make p jump a short distance } } public class GhostState implements PowerupState { public void jump(Player p) { // Significant difference in code: Jump through other objects } }

Also: FastState, GhostState, … Game Problem 4 44 jonkv@ida

 Plug in a behavior mode: public class Player { private PowerupState pstate; public Player() { this.pstate = new NormalState(); } public void jump() { … // Ask the state object to do the actual jump – delegate! pstate.jump(this); … If you get a new powerup: } this.pstate = new FasterState(); } Game Problem 5 45 jonkv@ida

 Expressed in UML notation: Player PowerupState<> pstate: PowerupState jump() jump() run() run() … …

NormalState GhostState FastState

jump() jump() jump() run() run() run() … … … 1 46 jonkv@ida

 Generalization to a State Pattern Context State <>

+ request() + doSomething()

ConcreteStateA ConcreteStateB ConcreteStateC

+ doSomething() + doSomething() + doSomething() State Pattern 2 47 jonkv@ida

 If you only want to represent "which state I'm in": . No need for State pattern – just use an enum public enum PlayerMode { NORMAL, // Standard mode STRONGER, // Stronger and less vulnerable FASTER, // Runs faster GHOST, … // Can walk, run or jump through solid matter }

 To implement different complex behaviors for each state: . Could use the state pattern public interface PowerupState { public void jump(); } public class NormalState implements PowerupState { public void jump() { … } } State vs. Strategy 48 jonkv@ida

 Looks similar to Strategy… . Similar Class diagrams – because we use delegation . But we use the classes differently!

 State:  Strategy: . There is an object whose behavior . There is an object whose behavior can be switched dynamically can be configured during the object’s lifetime when the object is created ▪ Player receives / loses powerups ▪ StringSorter needs a sort order . You want to separate code for the . You want to separate code for the different behaviors different behaviors . Solution: The State pattern, . Solution: The Strategy pattern, where the state where the strategy is dynamically changed is usually specified once, by the object itself generally by the caller Several States 49 jonkv@ida

 A class can use several state objects Player StrengthState<>

sstate: StrengthState Strength determines what vstate: VulnerabilityState jump() happens when you jump, run() run, … …

VulnerabilityState<>

Vulnerability determines absorbAttack() what happens when you … are attacked

 Avoids the need to create one state for each combination of strength / vulnerability State and Inheritance 50 jonkv@ida

 Inheritance can still be used to avoid code duplication . But between States, not between Players

PowerupState

General behaviors inherited AbstractState by default by subclasses

NormalState StrongState FastState Appropriate Use 1 51 jonkv@ida

 Use the State pattern only when its flexibility is needed! public class Player { private boolean jumpsHigh; Only two options: High or not high public void jump() { if (jumpsHigh) { Localized effects // Jump a bit higher (here: a single method) } else { // Ordinary jump  Stick with a simple flag; } State pattern too complex! } } Appropriate Use 2 52 jonkv@ida

 Use the State pattern only to modify behaviors (code)! public class Player { private int leapLength; Only a value differs public void leapForward() {  this.x += leapLength; Stick with a simple field; } State pattern too complex! }

class DefaultState implements StrengthState { public void leapForward() { player.x += 10; } class SuperState implements StrengthState { } public void leapForward() { player.x += 20; } }

MVC 1: Intro 54 jonkv@ida

 User interfaces need to: Te x t field Bar chart Dropdown Store String Column names, List of items data points Visualize Rasterize, display Paint bars, grid lines, … Show list Manipulate Accept text input Drag bars up/down Activate, deactivate, select item

 Could create a single class per component . Storage, visualization, manipulation MVC 2: Problems 55 jonkv@ida

. How to visualize the same data differently?

Reimplement data storage for each visualization?

. How to visualize the same data in many locations?

Store data in both the table and the graph?

Difficult to synchronize! MVC 3: Model 56 jonkv@ida

 Step 1: Extract a model class . Stores all relevant information . May support advanced operations on the information

TextModel PlayerModel class TextModel { class PlayerModel { String text; int xpos, ypos; int cursorPosition; Orientation leftright; void insertAtCursor(String str) { … } List carrying; … … } } MVC 4: View/Controller 57 jonkv@ida

 Could then use a combined view/controller

TextModel class TextModel { String text; int cursorPosition; void insertAtCursor(String str) { … } … } TextComponent class TextComponent { TextModel contents; // + Visualization // + Keyboard/mouse input }

Separation of concerns: Models know nothing about visualization, and vice versa MVC 5: Model + View/Controller in Swing 58 jonkv@ida

 For any Swing component: . One or more Models define its state ▪ JButton  ButtonModel ▪ JList  ListModel and ListSelectionModel

. A combined View/Controller defines the graphical interface ▪ How the information in the model is shown ▪ How the information in the model can be manipulated

. Several Views/Controllers can show the same Model ▪ Synchronize a toolbar button and a checkbox menu item ▪ Table data shown in a table view and a graph view ▪ final PlainDocument doc = new PlainDocument(); pane.add("West", new JTextArea(doc, null, 10, 30)); pane.add("East", new JTextArea(doc, null, 10, 30)); MVC 6: Further Separation 59 jonkv@ida

 Pure MVC: Separate three distinct responsibilities! . A model stores all relevant information . Zero or more views display this information . Zero or more controllers can alter the information

 For example, a Player: . Model class/object: ▪ Coordinates? Header ▪ Facing left or right? x ▪ Carrying a package? y orient ▪ … . View class/object: ▪ When requested, reads the model and displays it on screen . Controller class/object: ▪ One accepts keyboard input; asks the model to move left/right, etc. ▪ One accepts joystick input MVC 7: Notification 60 jonkv@ida

 It is useful for the views to be notified about model changes . This can be done using the Observer pattern (Keyboard) Controller (Mouse) Controller Due to keyboard input, Dragged a bar in a chart cell [5,20] should change  cell [9,13] should change

commitValue()

Model Views do not have to be observers: commitValue() Can use other techniques (polling, direct calls) changes the cell, MVC and Observer are separate patterns notifies all observers that can be combined if you want notifyCellChanged()

View Recalculator Some observers Repaints relevant parts Recalculates part of the are not views! of the screen spreadsheet

Terminology 62 jonkv@ida

 In general: . A factory creates things (objects) for you . A factory method is a method that creates things (objects) for you ▪ public class Integer { public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); } }

 In design patterns: . The is a specific pattern using factory methods in a particular way

Not all factory methods follow the factory method pattern! Factory Method Pattern 1 63 jonkv@ida

 A game creating enemy objects: public class Game { public void playGame() { // ... Enemy enemy = new SimpleEnemy(); The concrete enemy class SimpleEnemy // ... is hardcoded (fixed) at this point } }

 Now we want different game variations . Represented as subclasses of Game . Each creates a different enemy type . Other parts are similar Factory Method Pattern 2 64 jonkv@ida

 A "game skeleton" creating enemy objects: public abstract class Game { public void playGame() { // ... Enemy enemy = createEnemy(); Call a factory method in the same class // ... Implement this in subclasses } abstract protected Enemy createEnemy(); }

public class SimpleGame extends Game { protected Enemy createEnemy() { return new SimpleEnemy(); Subclasses specify the objects (types) } that are used by the superclass }

public class AIGame extends Game { protected Enemy createEnemy() { return new AIEnemy(); } } Factory Method Pattern 3 65 jonkv@ida

Creator AbstractProduct <> We want the ability to change operation() which type of object is created factoryMethod() Solution: each subclass has its own implementation of a factory method  Factory method pattern

ConcreteCreator1 ConcreteProduct1 <>

factoryMethod()

ConcreteCreator2 <> ConcreteProduct2

factoryMethod()

ConcreteCreator3 (Many concrete game variations may use the same enemy class) factoryMethod() Not a Pattern 66 jonkv@ida

 Not a design pattern: ▪ public class Integer { public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); } } ▪ A factory method, but not a factory method pattern in class organization!

Conclusions 68 jonkv@ida

 Correct use: Let the needs of the software drive you . Be aware of patterns . When implementing, consider whether a pattern is relevant . If so, decide whether it is truly useful ▪ For you ▪ In this piece of software ▪ For this particular purpose .  Use it – or don’t!

. Don’t try to squeeze in as many patterns as possible ▪ Class library analogy: ”Oh no! I haven’t used LinkedList! Maybe I could change the design so that I need linked lists somewhere!” Conclusions 2 69 jonkv@ida

Som tips till framtida elever så kan vi rekommendera att verkligen tänka på Det vi lärde oss mest under projektet har nog varit objektorientering och hur att strukturera upp sin kod och följa ett program blir märkbart mer designmönster. modulärt genom designmönster som verkligen underlättar för en, Till en början kan det kännas lättare att speciellt i slutskedet av göra lite som man vill men det blir kodningsprocessen när man ska minnas ganska snart ohållbart när man har flera hur alla klasser och metoder hänger hundra rader av kod som man ska sätta ihop, vad de innehåller och hur de sig in i efter att man kanske inte har kommunicerar med varandra. arbetat med koden på ett tag, eller om någon utomstående ska förstå den.