Svar och lösningar till tentamen 150605

del 1

1) A: Template Method    B: Strategy     C: Proxy    D: Iterator     E: Facade
 
2)     CSC
* vid Spec anger att en Center kan ha många objekt av Spec. Det syns i koden på att Center har en ArrayList med Spec-objekt.

3) Mönstret är Observer. Klassen Center motsvarar Observable (eller Subject) i standardbeskrivningen av mönstret. Observer i standardbeskrivningen motsvaras av interfacet Spec (spectator) i uppgiften.

4a) I testdriven programutveckling skrivs testfallen innan koden skrivs. Kod skrivs och testas, skrivs om, testas igen o.s.v. tills alla tester lyckas. Då skrivs nya tester för nästa omgång (sprint).
4b) Kod struktureras om och förbättras utan att programmets funktionalitet ändras.
4c) Det finns många att välja på: Parprogrammering, kundnärvaro i projektet, "the planning game", enklast möjliga design, alla i projektet äger koden.
4d) Rapid Prototyping innebär att man tar fram en prototyp (oftast grafisk) som visar hur det färdiga programmet kommer att se ut men inte alls har de funktioner som det färdiga programmet ska ha. Utifrån prototypen väljs funktioner att gå vidare med.

5a) Utskriften blir RUN
Objektets typ (och inte referensens typ) bestämmer vilken metod som körs.
Objektet är av typ Athlete och då skriver metoden activitiy ut RUN.
5b) Alternativ A är fel. Ett godtyckligt objekt av typ Object kan inte inta platsen som Person. En Person förväntas t.ex. ha metoden activity() och det har ju inte alla som är Object.

6) En abstrakt klass i Java kan ha vanliga metoder och variabler (både instans- och klass-) men har vanligen minst en metod där endast huvudet (typ, namn och parameterlista) är deklarerat. Sådana metoder markeras med abstract och måste definieras om i någon subklass för att objekt ska kunna instansieras. Nyttan med en abstrakt klass jämfört med att göra samma sak med vanliga klasser och arv är säkerhet (den abstrakta klassen kan inte instansieras) och tydlighet: man ser tydligt vilka egenskaper som är helt gemensamma och vilka är gemensamma men polymorfa.

7) Klassen A måste implementera interfacet Comparable (helst Comparable<A>) som finns i Java-API:n. Att A implementerar Comparable betyder att A måste ha metoden compareTo. compareTo tar en parameter av typ Object (eller A) och jämför objektet självt med parametern. Ett heltal som anger ordningen mellan objekten ska returneras, noll betyder att objekten är lika i sorteringsordningen.

8) Påståendena B, E, G och H är korrekta.

del 2

9)
class Particle {
    static int numOfPart = 0;  //exists before any objects of Particle and shared by all objects
    int x, y;                  
    Particle (int x, int y) {
        this.x = x; this.y = y;
        numOfPart++;            // count each object when created
    }
    static int getNumber() {    
        return numOfPart;
    }
} 
Anrop av metoden: Particle.getNumber()
Klassmetoder anropas via klassnamnet.

10) En fabriksmetod är en metod som skapar objekt. Användaren av klassen får objekt genom metodanrop som t.ex. TheClass.getInstance() istället för new TheClass(). Exempel på användning är

1) Att klassen själv (TheClass) ska kontrollera antalet skapade objekt. Nytt objekt kanske inte alltid måste skapas.
2) Att klassen själv ska bestämma vilken subklass som ska användas. Användaren kanske inte får bestämma (som i en av kursens labbar) eller ska inte behöva bestämma.
3) Om man egentligen skulle velat ha flera konstruktorer med samma signatur så kan fabriksmetoder lösa problemet.

En fabriksmetod måste alltid vara static. Konstruktorn får inte vara åtkomlig för användaren för i så fall går det att göra new TheClass() . private ger konstruktorn totalskydd men ofta är paketsynlighet tillräckligt.

11) Metoden Collections.sort(myList) finns i en variant som tar ytterligare en parameter:

 
    Collections.sort(myList, comp)
Här behöver inte objekten i myList vara av typ Comparable men de får vara det, det spelar ingen roll. Objektet comp ska vara av typen Comparator<A> där A är typen för objekten i myList. Comparator är ett interface med en enda metod. Metoden tar två obekt av typen A och jämför dem med varandra. Ett heltal returneras precis som av metoden compareTo() i interfacet Comparable. En del av sorteringsalgortimen tillhandahålls i objektet comp. Mönstret är Strategy.

12) Methods add(), remove() and size() are straightforward to implement.

Findbigdir must sort the contents of the current Directory. A natural way to do it is to make all FileElement-objects Comparable and sort them with Collections.sort(). To put Comparable on Directory is no good. Then you cannot compare Directories with Files which is necessary here.

Method moveup() does not require any changes to the existing classes. Move each element of the content list up to parent. After that, remove the directory from parents content list.

Method moveupR() is implemented by first adding all files (recursively from the subdirectories) to the parent, without removing any Files or Directories from the structure. When all files are added to the parent, detach the current Directory from the structure. To remove FileElements while looping over them may cause Exceptions or just wrong answers. Therefore we do all removal after the recursion.

import java.util.*;
class Directory extends FileElement {
    ArrayList<FileElement> content;

    Directory (String n) {
	super(n);
	content = new ArrayList<FileElement>();
    }

    void add(FileElement fe) {
	content.add(fe);
	fe.parent = this;
    }

    void remove(FileElement fe) {
	content.remove(fe);
    }

    int size() {
	int sum = 0;
	for (FileElement fe : content)
	    sum += fe.size();
	return sum;
    }
 
    // FileElement must implement interface Comparable
    // and size() will be used in the comparison in method compareTo() 

    void findbigdir() {
	Collections.sort(content);
	for (FileElement fe : content)
	    System.out.println(fe.toString() + " " + fe.size());
    }

    void moveup() {
        if (this.parent == null)
            return;
	for (FileElement fe : content)
	    this.parent.add(fe);        
	parent.remove(this);
    }

    // method movefilesto() is abstract in FileElement and therefore 
    // implemented in File and in Directory
    // in File, it will only move the file itself
    // in Directory, the method is called on each FileElement in its content
    // in the usual Composite manner

    void movefilesto(Directory destination) {
	for (FileElement fe: content)
	    fe.movefilesto(destination);
    }

    // Move all Files in all subdirectories
    // After that, remove this directory from its parent 

    void moveupR() {
        if (parent == null)
            return;
	movefilesto(parent);  // move all files to this.parent
	parent.remove(this);  // remove this directory 
    }
 }
New class FileElement: A good way to implement findbigdir is to make the FileElements Comparable.
import java.util.*;
abstract class FileElement implements Comparable<FileElement>{
    String name;
    Directory parent = null; // each FileElement except the root must always
                             // have a reference to its parent

    FileElement (String n) {
	name = n;
    }

    public String toString() {
	return name;
    }

    public int compareTo(FileElement fe) {   // method size() is used although
	return fe.size() - this.size();      // it is not defined yet! 
    }                                        // Pattern Template Method!

    abstract void add(FileElement fe);
    abstract void remove(FileElement fe);
    abstract int size();
    abstract void movefilesto(Directory destination);
}
New class File: The method movefilesto is used for a clean solution to moveupR.
class File extends FileElement {
    int size;
    File (String n, int s) {
	super(n);
	size = s;
    }

    void add(FileElement fe) {}     // Suitable with error message or Exception
    void remove(FileElement fe) {}  // Suitable with error message or Exception

    int size() {
	return size;
    }

    void movefilesto(Directory destination) {
	destination.add(this);
    }
}