Yakalent
Yakalent

Reputation: 1152

Implement Factory Pattern

Currently I'm busy with implement the Factory Pattern into my Java Code. I've got these classes:

CipherStorage

public class CipherStorage {

    protected String transformation;
    protected String provider;
    protected String providerPair;

    public CipherStorage(String transformation, String provider, String providerPair){
        this.transformation = transformation;
        this.provider = provider;
        this.providerPair = providerPair;
    }
}

CipherStorageProcessor (Interface)

public interface CipherStorageProcessor {
    byte[] encryptData(String keyName, String input, @Nullable SharedPreferences pref);
    byte[] decryptData(String keyName, byte[] encrypted, @Nullable SharedPreferences pref);
}

CipherStorageRSA

public class CipherStorageRSA extends CipherStorage implements CipherStorageProcessor {

    public CipherStorageRSA(String transformation, String provider,String providerPair){
        super(transformation, provider, providerPair);
    }
}

CipherStorageAES

public class CipherStorageAES extends CipherStorage implements CipherStorageProcessor {

    public CipherStorageAES(String transformation, String provider, String providerPair){
        super(transformation, provider, providerPair);
    }
}

CipherStorageFactory

public class CipherStorageFactory {

    public CipherStorage getCipher(String cipherType) {
        if (cipherType == null) {
            return null;
        }
        if (cipherType.equalsIgnoreCase("AES")) {
            return new CipherStorageAES();

        } else if (cipherType.equalsIgnoreCase("RSA")) {
            return new CipherStorageRSA();

        }
    }
}

Is this code made any sense? Is it correct to add parameters into the factory? Is there an better way to this?

Already thanks for any help.

PS: i removed the two interface functions from the classes to prevent a lot of code.

EDIT:

When i create an instance of RSA for example:

CipherStorage RSA = CipherStorageFactory.getCipher("RSA");

I've got no access to the methods into the interface?

Upvotes: 2

Views: 252

Answers (2)

Elyor Murodov
Elyor Murodov

Reputation: 1028

  1. Regarding Factory Pattern

Your implementation of the factory pattern is correct.

Regarding constructor parameters of your concrete classes, you can preconfigure them into your factory object(as those parameters are common throughout different cipher objects that the factory creates), and use them to create instances within your factory method:

public class CipherStorageFactory {
    private String transformation;
    private String provider;
    private String providerPair;

    public CipherStorageFactory(String transformation, String provider, String providerPair){
        this.transformation = transformation;
        this.provider = provider;
        this.providerPair = providerPair;
    }

    public CipherStorage getCipher(String cipherType) {
        //...
        if (cipherType.equalsIgnoreCase("AES")) {
            return new CipherStorageAES(transformation, provider, providerPair);
        } else 
        //...
    }
}

Additionally, in this case, it is better to name your factory method like "createCipher()", as it's returning a new instance every time.

  1. Regarding the Interface Methods

The reason why you can't access encryptdata() method is that, because you are casting the created cipher object to super type(CipherStorage) and it doesn't have those methods. One of the options you can do is, move the 2 methods from your interface to CipherStorage and declare them (as well as the class itself) as abstract, and you won't need an interface in that case:

public abstract class CipherStorage {
    public abstract byte[] encryptData(String keyName, String input, @Nullable SharedPreferences pref);
    public abstract byte[] decryptData(String keyName, byte[] encrypted, @Nullable SharedPreferences pref);
}

Upvotes: 2

Vishwa Ratna
Vishwa Ratna

Reputation: 6390

Use the Factory Method pattern when

1.a class can't anticipate the class of objects it must create

2.a class wants its subclasses to specify the objects it creates

3.classes delegate responsibility to one of several helper subclasses, and you want to localize the knowledge of which helper subclass is the delegate

Upvotes: 1

Related Questions