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();
        }
        
    }
}
原文地址:https://www.cnblogs.com/wangyongwen/p/11255563.html