写点什么

算法策略的主动选择, 拒绝 if...else...(策略模式 + 简单工厂模式)

作者:小鑫同学
  • 2022-10-13
    北京
  • 本文字数:3480 字

    阅读完需:约 11 分钟

算法策略的主动选择,拒绝if...else...(策略模式+简单工厂模式)

大家好,我是小鑫同学。一位从事过 Android 开发混合开发,现在长期从事前端开发的编程爱好者,我觉得在编程之路上最重要的是知识的分享,所谓三人行必有我师。所以我开始在社区持续输出我所了解到、学习到、工作中遇到的各种编程知识,欢迎有想法、有同感的伙伴加我fe-xiaoxin微信交流~

算法策略的主动选择,拒绝 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 StrategyTypefrom impl.AesStrategy import AesStrategyfrom 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("---------------结束测试-------------------")
复制代码


发布于: 刚刚阅读数: 5
用户头像

小鑫同学

关注

⚡InfoQ签约作者 2018-12-10 加入

还未添加个人简介

评论

发布
暂无评论
算法策略的主动选择,拒绝if...else...(策略模式+简单工厂模式)_前端_小鑫同学_InfoQ写作社区