算法策略的主动选择,拒绝if...else...(策略模式+简单工厂模式)
本文通过一个切换加解密算法的Demo来学习如何使代码的调用和封装都变的更加简单
1. 抽象策略接口
/** * 加密算法接口:封装算法的公共操作加密和解密 * * @author Spoon * @version 1.0.0 */ public interface SecurityStrategy { /** * 加密 */ public String doEncryption(String key, String plaintext); /** * 解密 */ public String doDeciphering(String key, String ciphertext); }
2. 策略算法的具体实现
/** * AES加密算法具体实现类 * * @author Spoon * @version 1.0.0 */ public class AesStrategy implements SecurityStrategy{ @Override public String doEncryption(String key, String plaintext) { String dec = ""; try { dec = AESUtil.encrypt(plaintext, key, "UTF-8"); } catch (Exception e) { e.printStackTrace(); } return dec; } @Override public String doDeciphering(String key, String ciphertext) { String enc = ""; try { enc = AESUtil.decrypt(ciphertext, key); } catch (Exception e) { e.printStackTrace(); } return enc; } }
/** * DES3加密算法具体实现类 * * @author Spoon * @version 1.0.0 */ public class Des3Strategy implements SecurityStrategy{ @Override public String doEncryption(String key, String plaintext) { String dec = ""; try { dec = ThreeDES.encode(plaintext, key); } catch (Exception e) { e.printStackTrace(); } return dec; } @Override public String doDeciphering(String key, String ciphertext) { String enc = ""; try { enc = ThreeDES.decode(ciphertext, key); } catch (Exception e) { e.printStackTrace(); } return enc; } }
3. 加密算法类型枚举
/** * 加密算法类型枚举 * @author Spoon * @version 1.0.0 */ public enum StrategyType { AES(1,"AES加密算法"), DES3(2,"DES3加密算法"); private int index; private String desc; private StrategyType(int index, String desc){ this.index = index; this.desc = desc; } public int index() { return index; } public String desc() { return desc; } }
4. 使用简单工厂获取具体实现
/** * 策略工厂类:将每个实现策略注册到工厂,并根据Type返回指定策略实现 * @author Spoon * @version 1.0.0 */ public class StrategyFactory { private static Map<Integer, SecurityStrategy> services = new ConcurrentHashMap<Integer, SecurityStrategy>(); static { services.put(StrategyType.AES.index(), new AesStrategy()); services.put(StrategyType.DES3.index(), new Des3Strategy()); } private StrategyFactory() { } public static SecurityStrategy getSecurity(Integer type) { return services.get(type); } }
5. 策略上下文完成工厂返回实现的具体调用
/** * 策略上下文:实际操作对象,接收传入的Type和必要参数,内部调用策略工厂类获取实际实现类进行加解密操作 * * @author Spoon * @version 1.0.0 */ public class StrategyContext { private SecurityStrategy strategy; public StrategyContext() { } public SecurityStrategy getStrategy() { return strategy; } public void setStrategy(SecurityStrategy strategy) { this.strategy = strategy; } public String executeEncryptionStrategy(Integer type, String key, String plaintext) { strategy = StrategyFactory.getSecurity(type); return strategy.doEncryption(key, plaintext); } public String executeDecipheringStrategy(Integer type, String key, String ciphertext) { strategy = StrategyFactory.getSecurity(type); return strategy.doDeciphering(key, ciphertext); } }
6. Test
/** * 测试类 * String key_aes = "789tenc963qAzWsX"; * String key_des3 = "1234567890ASDFGH12345678"; */ public class Main { @SuppressWarnings("resource") public static void main(String[] args) { String plaintext = "ABCDEFGHIJKLMNOPQRST"; System.out.println("请选择加密算法(AES:1, DES3:2) :"); int type = new Scanner(System.in).nextInt(); System.out.println("请输入加密秘钥 :"); String key = new Scanner(System.in).nextLine(); StrategyContext context = new StrategyContext(); System.out.println(context.executeEncryptionStrategy(type, key, plaintext)); } }
通过测试Main方法可以看出,在增加加密算法后对调用方来说只需要关注加密算法的Type值就可以,调用形式也没有发生改变,没有使用条件语句进行判断,减少了调用时出错的风险,对于提供方来说,主要关注点就是策略算法的具体实现,并添加相应的枚举后将实现的策略注册到策略工厂中即可。
Python版本 :
from abc import ABCMeta,abstractmethod class SecurityStrategy: __metaclass__ = ABCMeta # 指定这是一个抽象类 @abstractmethod # 抽象方法 def doEncryption(self, key, plaintext): pass @abstractmethod # 抽象方法 def doDeciphering(self, key, ciphertext): pass
from SecurityStrategy import SecurityStrategy class AesStrategy(SecurityStrategy): def doEncryption(self, key, plaintext): print('AES === > ', 'key : ', key, 'plaintext : ', plaintext) def doDeciphering(self, key, ciphertext): print('AES === > ', 'key : ', key, 'ciphertext : ', ciphertext)
from SecurityStrategy import SecurityStrategy class Des3Strategy(SecurityStrategy): def doEncryption(self, key, plaintext): print('Des3 === > ', 'key : ', key, 'plaintext : ', plaintext) def doDeciphering(self, key, ciphertext): print('Des3 === > ', 'key : ', key, 'ciphertext : ', ciphertext)
from enum import Enum class StrategyType(Enum): AES = 1 DES3 = 2
from StrategyType import StrategyType from impl.AesStrategy import AesStrategy from impl.Des3Strategy import Des3Strategy class StrategyFactory: services = { StrategyType.AES.value: AesStrategy(), StrategyType.DES3.value: Des3Strategy() } @staticmethod def getSecurity(type): return StrategyFactory.services[type]
from StrategyFactory import StrategyFactory class StrategyContext: @staticmethod def executeEncryptionStrategy(type, key, plaintext): return StrategyFactory.getSecurity(type).doEncryption(key, plaintext) @staticmethod def executeDecipheringStrategy(type, key, ciphertext): return StrategyFactory.getSecurity(type).doDeciphering(key, ciphertext)
from StrategyContext import StrategyContext if __name__ == '__main__': print("---------------开始测试-------------------") StrategyContext.executeEncryptionStrategy(1, '1234567890ASDFGH12345678', 'ABCDEFGHIJKLMNOPQRST') StrategyContext.executeDecipheringStrategy(1, '1234567890ASDFGH12345678', 'ABCDEFGHIJKLMNOPQRST') StrategyContext.executeEncryptionStrategy(2, '1234567890ASDFGH12345678', 'ABCDEFGHIJKLMNOPQRST') StrategyContext.executeDecipheringStrategy(2, '1234567890ASDFGH12345678', 'ABCDEFGHIJKLMNOPQRST') print("---------------结束测试-------------------")