© 1999-2003, Flemming Koch Jensen
Alle rettigheder forbeholdt
Composite
Vejledende løsninger

 

 

1 Vi vil ikke gennemgå løsningen for hver delopgave, men i stedet tage en klasse af gangen:
Først er der Node-klassen (Component-klassen):
public abstract class Node {
  private String name;
  
  public Node( String name ) {
    this.name = name;
  }
  
  public abstract boolean findFile( String name );
  public abstract int size();
  public abstract void list();
  
  public String toString() {
    return name;
  }
}
Vi gør denne klasse abstrakt, da vi ikke ønsker, at den skal kunne instantieres. Samtidig vælger vi at lave en abstrakt klasse i stedet for et interface, da vi implementerer den fælles egenskab: navnet.
Bemærk at toString-metoden giver os den fornødne adgang til navnet fra subklasserne.
 
Dernæst laver vi File-klassen (Leaf-klassen):
public class File extends Node {
  private int size;
  
  public File( String name, int size ) {
    super( name );
    
    this.size = size;
  }
  
  public boolean findFile( String name ) {
    return super.toString().equals( name );
  }

  public int size() {
    return size;
  }
  
  public void list() {
    System.out.println( this );
  }

  public String toString() {
    return super.toString() + " " + size;
  }
}
Eftersom vi befinder os i Leafs, er metoderne meget enkle. Bemærk at list ikke gør noget - det skyldes at list-metoden i Directory-klassen udskriver filernes navne.
 
Dernæst kommer Directory-klassen (Composite-klassen), hvor det meste af arbejdet foregår:
import java.util.LinkedList;

public class Directory extends Node {
  protected LinkedList<Node> nodes;
  
  public Directory( String name ) {
    super( name );
    
    nodes = new LinkedList<Node>();
  }
  
  public void insert( Node node ) {
    nodes.add( node );
  }
  
  public boolean findFile( String name ) {
    for ( Node node : nodes )
      if ( node.findFile( name ) )
        return true;
    
    return false;
  }
  
  public int size() {
    int sum = 0;
    
    for ( Node node : nodes )
      sum += node.size();
      
    return sum;
  }
  
  public void list() {
    System.out.println( this );

    for ( Node node : nodes )
      node.list();
  }
  
  public String toString() {
    return "[" + super.toString() + "]";
  }
}
insert-metoden er blot en delegering til den linkede liste.
De tre metoder: findFile, size og list har en vis lighed med hinanden, idet de alle gennemløber børnene og kalder dem med den samme metode som dem selv. list adskiller sig lidt, idet den først udskriver alle børnene og dernæst kalder dem.
 
Endelig har vi testanvendelsen:
public class Main {
  
  public static void main( String[] args ) {
    Directory root, sub1, sub2, sub3;
    
    root = new Directory( "" );
    sub1 = new Directory( "Sub1" );
    sub2 = new Directory( "Sub2" );
    sub3 = new Directory( "Sub3" );
    
    root.insert( sub1 );
    root.insert( sub2 );
    sub1.insert( sub3 );
    
    root.insert( new File( "file01", 2000 ) );
    root.insert( new File( "file02", 3000 ) );
    root.insert( new File( "file03", 15000 ) );
    
    sub1.insert( new File( "file11", 312 ) );
    sub1.insert( new File( "file12", 42200 ) );
    
    sub2.insert( new File( "file21", 400 ) );
    
    sub3.insert( new File( "file31", 55000 ) );
    
    System.out.println( root.findFile( "file21" ) );
    System.out.println( root.findFile( "file22" ) );
    
    System.out.println( root.size() );
    
    root.list();
  }
}

true
false
117912
[Sub1]
[Sub2]
file01 2000
file02 3000
file03 15000
[Sub3]
file11 312
file12 42200
file31 55000
file21 400

Kildetekster:

Node.java
File.java
Directory.java
TestDirectory.java