0

I just started learning coding (mainly Java) for about 6 months at a University and now we just covered section of Composite design pattern (with Component, Leaf and Composite classes).

My class problem requires I use the below Component Interface to make a simple director program that I can create/add/remove files/directory.

public interface Component {
    public String getName();
    public int getSize();
    public int getCount();
    public String display(String prefix);
    public Component search(String name);
}

Below is the File class that I wrote to be used as Leaf

public class File implements Component { 
    private String name;
    private int size;
    public File(String name, int size){
        this.name = name;
        this.size = size;
    }
    
    @Override
    public String getName() {
        return this.name;
    }
    
    @Override
    public int getSize() {
        return this.size;
    }
    
    @Override
    public int getCount() {
        return 1;
    }
    
    @Override
    public String display(String prefix) {
        return this.name + " " + "(" + this.size + ")" + System.lineSeparator();
    }
    
    @Override
    public Component search(String name) {
        if(this.name.equals(name)){
            return this;
        }
        else {
            return null;
        }
    }

Below is the Component Class - Directory Class. I put line of * above the method display in question.

import java.util.ArrayList;

public class Directory implements Component {
    static int count = 0;
    private String name;
    //Array List to store the leafs
    public ArrayList<Component> children;

    public Directory(String name){
        this.name = name;
        this.children = new ArrayList<>();
    }

    //Method to add leaf to Directory
    public void add(Component component){
        children.add(component);
    }

    //Method to remove leaf from Directory
    public void remove(Component component){
        children.remove(component);
    }

    @Override
    public String getName() {
        return this.name;
    }

    @Override
    public int getSize() {
        int size = 0;
        for(Component component : children) {
            size += component.getSize();
        }
        return size;
    }

    @Override
    public int getCount() {
        int count = 0;
        for(Component component : children) {
            count += component.getCount();
        }
        return count;
    }

//***********************************
    @Override
    public String display(String prefix) {
        String totalString = name + ": (count=" + getCount() + ", size=" + getSize() + ")" + System.lineSeparator();

        for (Component component : children) {
            totalString = totalString + prefix + component.display(prefix + prefix);
        }
        return totalString;
    }

//*************************************
    @Override
    public Component search(String name) {
        for(Component component: children) {
            if (component.search(name) != null) {
                return component;
            }
        }
        return null;
    }
}

My goal is, when I apply the display method, every-time the component has children, the prefix in display method should increase by 1. To clarify, below is my test method

public class Test3 {

    public static void main(String[] args) {
        File holiday = new File("family-holiday",201);
        File wallpaper = new File("wallpaper", 421);
        Directory pictures = new Directory("pictures");
        Directory personal = new Directory("personal");
        Directory misc = new Directory("misc");
        Directory dog = new Directory("dog");
        dog.add(wallpaper);
        personal.add(holiday);
        personal.add(misc);
        pictures.add(personal);
        misc.add(dog);

        System.out.print(pictures.display("+"));
    }
}

The result of this should be

pictures: (count=2, size=622)
\+personal: (count=2, size=622)
\++family-holiday (201)
\++misc: (count=1, size=421)
\+++dog: (count=1, size=421)
\++++wallpaper (421)

However, due to the display method when component has children, it calls (prefix + prefix) which works until the 3rd directory/files, the prefix gets doubled every time instead of an increment of one. Below is the result I got

pictures: (count=2, size=622)
\+personal: (count=2, size=622)
\++family-holiday (201)
\++misc: (count=1, size=421)
\++++dog: (count=1, size=421)
\++++++++wallpaper (421)

I have tried multiple ways that I can think of below

  • Add prefix at the File display : This obviously did not work if there is director inside directory

  • Use static parameter to count number of method getting called, since the number of times prefix should be used depends on how many level the file / director is in there, that doesn't work with full count of the number of times used by the method.

  • Adding prefix at MANY MANY different places .. :) Still did not work well. I can imagine it has to be the way I pass the prefix to when the loop is calling display again, but I can't figure out what it is ...

If you could please advise or guide on what I can do or what I should read on to help with this, that will be very helpful. I do apologise in advance if there is similar topics as I couldn't find them with my current knowledge of the keyword, if you could please guide me there then I'm very grateful

4
  • You can see why, right? When you have prefix='++', you then pass prefix+prefix, or ++++. It would be a better plan to pass "depth" as an integer to describe how deep you are, then construct the prefix by repeating the '+' that many times. Then you just pass depth+1. Commented Feb 6, 2023 at 19:03
  • Hi Tim, thank you for the feedback. Indeed I understand that prefix + prefix is not the best method .. just the only one I can think of ! Since the purpose of this exercise is to implement the given interface (Fix by the problem), I don't think I can change the display method that was specified to have additional input ? If possible, that will definitely help solve the problem. Please let me know if you have any other thought! Thank you very much for answering. Commented Feb 6, 2023 at 19:51
  • I told you how to do it. Don't pass the prefix string, pass the current depth. Have your "display" function accept a int depth. Now, it can construct the prefix string by repeating the '+' that many times. Commented Feb 6, 2023 at 20:40
  • Which Java version are you using? Commented Feb 6, 2023 at 20:44

2 Answers 2

0

As I said, just pass the depth as an integer and construct the prefix within the display function.

    @Override
    public String display(int depth) {
        String prefix = '+'.repeat(depth);
        String totalString = name + ": (count=" + getCount() + ", size=" + getSize() + ")" + System.lineSeparator();

        for (Component component : children) {
            totalString = totalString + prefix + component.display(depth + 1);
        }
        return totalString;
    }

...

        System.out.print(pictures.display(1));
Sign up to request clarification or add additional context in comments.

Comments

0

I see several issues in your code but won't address all of them here as this is not https://codereview.stackexchange.com.

But important: don't concatenate String in a loop with the + or += operators. Use java.lang.StringBuilder for this.

Instead of doubling your prefix, you can calculate the new prefix from the first char and the size of the input prefix. Here is just the Directory.display method:

@Override
public String display(String prefix) {
  StringBuilder totalString = new StringBuilder(name);
  totalString.append(": (count=").append(getCount());
  totalString.append(", size=").append(getSize()).append(")");
  totalString.append(System.lineSeparator());

  for (Component component : children) {
    totalString.append(prefix).append(component.display(prefix.substring(0, 1).repeat(prefix.length() + 1)));
  }
  return totalString.toString();
}

This way you can keep your given interface exactly as before. Still @TimRoberts answer is probably more efficient and performant, but doesn't keep your interface the same.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.