• Java的设计模式(5)-- 策略模式


      定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换,本模式使得算法可以独立于使用它的客户而变化。策略模式包括以下三种角色

    • 策略(Strategy):策略是一个接口,该接口定义若干个算法标识,定义了若干个抽象方法。
    • 具体策略(ConcreteStrategy):具体策略是实现策略接口的类,具体策略实现策略接口所定义的抽象方法,给出算法标识的具体算法。
    • 上下文(Context):上下文是依赖策略接口的类,即上下文包含有策略声明的变量。上下文中提供一个方法,该方法委托策略变量调用具体策略所实现的策略接口中方法。

      策略模式的UML类图如下图所示:

    策略模式的优点:

      上下文和具体策略是松耦合的关系,上下文只知道它要使用某一个实现Strategy接口类的实例,但不需要知道具体是哪一类。

      策略模式满足“开-闭原则”。当增加新的具体策略时,不需要修改上下文类的代码,上下文就可以引用新的具体策略实例。

    策略模式的使用场景:

      一个类定义了多种行为,并且这些行为在这个类的方法中以多个条件语句的形式出现,那么可以使用策略模式避免在类中使用大量的条件语句。

      程序不希望暴露复杂的。与算法相关的数据结构,可以使用策略模式封装算法。

      需要使用一个算法的不同实体。

    应用举例 —— 加密、解密文件

      用户需要对已有的文件进行加密处理,请提供几种加密方案。

     设计实现可以使用策略模式,具体如下:

      1. 策略接口的名称是EncryptStrategy,该接口有两个抽象方法,一个是加密,一个是解密

    public interface EncryptStrategy {
    	public abstract void encryptFile(File file);
    	public abstract void decryptFile(File file);
    }
    

      2. 具体策略,有两个具体策略,StrategyONE和StrategyTWO

      • StrategyONE使用一个字符串做密码,比如password,将这个字符串编码到一个字节数组,byte[] e = password.getBytes(); 假设e的长度是n,那么就将文件内容以n字节为一组,对每组中字节,用数组e对应字节做加法运算,解密的话就是相应的做减法运算。
      • StrategyTWO使用一个字符串做密码,比如password,将这个字符串编码到一个字节数组,byte[] e = password.getBytes(); 假设e的长度是n,那么就将文件内容按顺序以n字节为一组对每组中字节,使用数组e的对应字节做异或运算
    public class StrategyOne implements EncryptStrategy {
        String password;
    
        public StrategyOne(String password) {
            if(password == null||password.trim().length()==0)
                this.password = "I love java";
            this.password = password;
        }
        public StrategyOne() {
            this.password = "I love java";
        }
        public void encryptFile(File file) {
            try {
                byte[] a = this.password.getBytes();
                FileInputStream fis = new FileInputStream(file);
                long length = file.length();
                byte[] c = new byte[(int)length];
                int m = fis.read();
                for (int i = 0; i < m; i++) {
                    int n = c[i]+a[i%a.length];
                    c[i] = (byte) n;
                }
                fis.close();
                FileOutputStream fos = new FileOutputStream(file);
                fos.write(c, 0, m);
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        public void decryptFile(File file) {
            try {
                byte[] a = this.password.getBytes();
                FileInputStream fis = new FileInputStream(file);
                long length = file.length();
                byte[] c = new byte[(int)length];
                int m = fis.read();
                for (int i = 0; i < m; i++) {
                    int n = c[i]-a[i%a.length];
                    c[i] = (byte) n;
                }
                fis.close();
                FileOutputStream fos = new FileOutputStream(file);
                fos.write(c, 0, m);
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
    }
    public class StrategyTWO implements EncryptStrategy {
        String password;
    
        public StrategyTWO(String password) {
            if(password == null||password.trim().length()==0)
                this.password = "I love java";
            this.password = password;
        }
        public StrategyTWO() {
            this.password = "I love java";
        }
    @Override
    public void encryptFile(File file) { try { byte[] a = this.password.getBytes(); FileInputStream fis = new FileInputStream(file); long length = file.length(); byte[] c = new byte[(int)length]; int m = fis.read(); for (int i = 0; i < m; i++) { int n = c[i]^a[i%a.length]; c[i] = (byte) n; } fis.close(); FileOutputStream fos = new FileOutputStream(file); fos.write(c, 0, m); fos.close(); } catch (IOException e) { e.printStackTrace(); } } @Override public void decryptFile(File file) { try { byte[] a = this.password.getBytes(); FileInputStream fis = new FileInputStream(file); long length = file.length(); byte[] c = new byte[(int)length]; int m = fis.read(); for (int i = 0; i < m; i++) { int n = c[i]^a[i%a.length]; c[i] = (byte) n; } fis.close(); FileOutputStream fos = new FileOutputStream(file); fos.write(c, 0, m); fos.close(); } catch (IOException e) { e.printStackTrace(); } } }

      3. 上下文,该类包含策略声明用于保存具体策略的引用变量,代码如下

    public class EncodeContext {
    
        public EncryptStrategy strategy;
    
        public void setStrategy(EncryptStrategy strategy) {
            this.strategy = strategy;
        }
        
        public void encryptFile(File file){
            this.strategy.encryptFile(file);
        }
        
        public void decryptFile(File file){
            this.strategy.decryptFile(file);
        }
    }

      4. 应用程序

    public class Application {
        public static void main(String[] args) {
            File fileOne = new File("A.txt");
            
            String s = "";
            EncodeContext con = new EncodeContext();
            con.setStrategy(new StrategyOne("Hello world!"));
            con.encryptFile(fileOne);
            System.out.println(fileOne.getName()+"加密后的內容:");
            try {
                FileReader inOne = new FileReader(fileOne);
                BufferedReader inTwo = new BufferedReader(inOne);
                while((s=inTwo.readLine())!=null){
                    System.out.println(s);
                }
                inOne.close();
                inTwo.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            
        }
    }
  • 相关阅读:
    浅析:setsockopt()改善socket网络程序的健壮性
    神奇的vfork
    2008级 毕业设计 题目
    Linux之父访谈录:设计内核只为了好玩
    启用Fedora的root账户登录
    Linux系统所使用的真实内存——free
    linux内核源码中常见宏标志tag
    c语言中的 顺序点
    tcpdump
    双系统中从Windows访问Linux分区 ext2 ext3 的三种方法
  • 原文地址:https://www.cnblogs.com/wangyongwen/p/11255563.html
Copyright © 2020-2023  润新知