Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何避免API/库中的并行继承层次结构_Java_Design Patterns - Fatal编程技术网

Java 如何避免API/库中的并行继承层次结构

Java 如何避免API/库中的并行继承层次结构,java,design-patterns,Java,Design Patterns,我正在开发一个加密库,以简化我的团队如何对api凭据使用加密,以及如何从其他团队/项目接收加密消息 我从这些顶级接口开始定义域: public interface Key { public byte[] getBytes(); } public interface Message { public byte[] getBytes(); } public interface Secret { public byte[] getBytes(); } public int

我正在开发一个加密库,以简化我的团队如何对api凭据使用加密,以及如何从其他团队/项目接收加密消息

我从这些顶级接口开始定义域:

public interface Key {
    public byte[] getBytes();
}

public interface Message {
    public byte[] getBytes();
}

public interface Secret {
    public byte[] getBytes();
}

public interface Decrypter {
    public String decrypt(Secret secret, Key key);
}

public interface Encrypter {
    public Secret encrypt(Message message, Key key);
}
这对于包装RSA加密非常有效:

public class KeyPair {
    private final Key publicKey;
    private final Key privateKey;

    public Key getPublicKey() {
        return publicKey;
    }

    public Key getPrivateKey() {
        return privateKey;
    }
}

public class RsaEncrypter implements Encrypter {

    @Override
    public Secret encrypt(Message message, Key publicKey) {
        // Perform Encryption
    }
}

public class RsaDecrypter implements Decrypter {
    @Override
    public String decrypt(Secret secret, Key privateKey) {
        // Perform the decryption
    }
}
但是现在我将它应用到我们的AES加密用例中,我遇到了一个问题。这个秘密包含一个初始化向量,因为我们在CBC模式下使用AES

所以我有这个:

public class AesSecret implements Secret {
    private byte[] cipherText;
    private byte[] initilizationVector;

    @Override
    public byte[] getBytes() {
        return cipherText;
    }

    public byte[] getInitilizationVector() {
        return initilizationVector;
    }
}

public class AesDecrypter implements Decrypter {
    @Override
    public String decrypt(Secret secret, Key key) {
        try {
            return decrypt((AesSecret) secret, key);
        } catch (ClassCastException e) {
            throw new IllegalArgumentException("AesDecrypter only supports subclasses of AesSecret", e);
        }
    }

    public String decrypt(AesSecret secret, Key key) {
        // Do the AES Decryption
    }
}
ClassCastException让我觉得我违反了Liskov替换原则,引入了并行层次代码。我已经读过Visitor模式是这种代码气味的常见解决方案,但我还没有弄清楚它如何适用于我的情况

有什么建议吗?还是我想得太多了


我已经在要点中添加了这些类:

您可以将解密程序设置为通用的。大概是这样的:

interface Decryptor<S extends Secret>{
    public String decrypt(S secret, Key publicKey);
}

这样,解密器的每个实现都可以定义自己的秘密。这样你就可以摆脱铸造。

仿制药。使en/解密程序在机密中通用。Create和interface-CbcSecret,它扩展了Secret并添加了IV。此外,所有带有getBytes的接口似乎都在乞求某个父接口。接口上的公共方法让我很难过。最后,解密程序接收消息,加密程序返回字符串似乎很奇怪。我希望它们彼此相反。@aglassman只要使用可信的实现,就可以使用自己的API。关键是java.security有点棘手,需要正确处理;不熟悉它的人很可能会错误地使用它。用一个简单的API生成一个经过测试的正确用法将有助于防止这种情况。@aglassman:我实际上使用的是java.security。我们的存储库中有使用它的代码,但我花了几天时间对它的工作方式/原因进行逆向工程。因此,我将这些代码放入一个带有单元测试套件的共享库中,以便我们的其他项目可以使用简化的API。尽管如此,它仍然得到了可信库的支持。