Plain-text file encryption and decryption I have created an Encryption and Decryption Algorithm that encrypts plain text using a given cipher and also decrypts it back to the original notation. It works great.

This was my code for a coding test and the reviewer told me that the class structure is inverse of what is the right way of doing it and that it is sloppy at some places.

I want to know what is wrong with my structuring of classes, if anything. Does it look sloppy? Can someone please help me identify places where it is lacking Best Practices for Java?

I have a MyBuilder class which creates an instance of MyAlgorithm. 
MyAlgorithm has the methods to encrypt and decrypt text, and it extends another class called EncryptionAndDecryption where the actual logic of the algorithm resides.



public class MyAlgorithm extends EncryptionAndDecryption {

    public enum Action {
        ENCRYPT,
        DECRYPT
    }

    protected MyAlgorithm(final String cipherCharSet) {
        super(cipherCharSet);
    }

    public String encryptText(final String cipher, final String plainText) {
        return encryptOrDecryptText(cipher, plainText, Action.ENCRYPT);
    }

    public String decryptText(String cipher, String encryptedText) {
        return encryptOrDecryptText(cipher, encryptedText, Action.DECRYPT);
    }

    public boolean encryptDirectory(String cipher, String baseDirectory) {
        // for each files and sub files in each sub directories, call the following method;
    // encryptOrDecryptFile(cipher, file, baseDirectory, Action.ENCRYPT));
    }

    public boolean decryptDirectory(String cipher, String baseDirectory) {
        // for each files and sub files in each sub directories, call the following method;
    // encryptOrDecryptFile(cipher, file, baseDirectory, Action.DECRYPT));
    }
}


public class EncryptionAndDecryption {

    private final String CIPHER_CHAR_SET;

    protected EncryptionAndDecryption(final String cipherCharSet) {
        this.CIPHER_CHAR_SET = cipherCharSet;
    }

    protected final String encryptOrDecryptText(final String cipher, final String inputText, final MyAlgorithm.Action action) {
         // method logic here
    }

    protected final void encryptOrDecryptFile(final String cipher, final Path filePath, final String baseDirectory, final MyAlgorithm.Action action) {
        // method logic here
    }
}


public class MyBuilder {

    private String CIPHER_CHAR_SET;

    private MyBuilder() {}

    public static MyBuilder builder() {
        return new MyBuilder();
    }

    public MyBuilder withCipherSet(String cipherSet) {
        this.CIPHER_CHAR_SET = cipherSet;
        return this;
    }

    public MyAlgorithm build() {
        return new MyAlgorithm(CIPHER_CHAR_SET);
    }
}


public class MyEncryptionApp {

    public static final String CIPHER_CHAR_SET = "abcdefghijklmnopqrstuvwxyz";

    public static void main(String args[]) {
        if (args.length != 3) {
            System.out.println("Exact 3 parameters required - [action] [key] [target]");
            System.exit(1);
        }

        String action, key, target;
        action = args[0];
        key = args[1];
        target = args[2];

        MyAlgorithm myAlgorithm = MyBuilder.builder()
                .withCipherSet(CIPHER_CHAR_SET)
                .build();

        if ("encrypt".equalsIgnoreCase(action)) {
            System.out.println(myAlgorithm.encryptText(key, target));

        } else if ("decrypt".equalsIgnoreCase(action)) {
            System.out.println(myAlgorithm.decryptText(key, target));

        } else if ("encryptDir".equalsIgnoreCase(action)) {

            if(myAlgorithm.encryptDirectory(key, target)) {
                System.out.println("Directory encryption Successful");
            }

        } else if ("decryptDir".equalsIgnoreCase(action)) {

            if(myAlgorithm.decryptDirectory(key, target)) {
                System.out.println("Directory decryption Successful");
            }

        } else {
            System.out.println("action [" + action + "] not implemented");
        }

    }
}
Hello and welcome to Code Review! I try to give a possible explanation of what the reviewer meant when he was talking about inverse class structure; in the main method this code is present:

MyAlgorithm myAlgorithm = MyBuilder.builder()
               .withCipherSet(CIPHER_CHAR_SET)
               .build();


But from your code MyAlgorithm is a subclass of EncryptionAndDecryption and this is the class where you defined the operations of encryption and decryption , so the method shoud have return an instance of class EncryptionAndDecryption instead of one subclass. 
Other problem: in the class EncryptionAndDecryption we have the below methods:

protected final String encryptOrDecryptText(final String cipher, final String inputText, final MyAlgorithm.Action action)

protected final void encryptOrDecryptFile(final String cipher, final Path filePath, final String baseDirectory, final MyAlgorithm.Action action)


With parameter MyAlgorithm.Action action the class EncryptionAndDecryption will be dependant from its subclass MyAlgorithm and without its subclass it cannot be even compiled.
In the class EncryptionAndDecryption I would make two distinct methods for encryption and decryption of strings, putting these related to files and directory in the subclass MyAlgorithm, deleting the enum value you are using to distinguish between the two operations.
Style problem : in the main method is present a list of if like this below:

if ("encrypt".equalsIgnoreCase(action)) {}


Normally it is the string compared to the string literal like:

if (action.equalsIgnoreCase("encrypt")) {}


You can substitute the list of if with a switch like documented in strings-switch.