[连载]Java程序设计(05)---任务驱动方式:简单的加密/解密系统

任务:还是上一家公司,现在该公司在全国各地都设立了自己的分公司以拓展其核心业务,那么就需要利用互联网在全国各地的公司之间传递信息(我们假定这些信息就是文字信息),这些信息可能涉及一些商业机密,为此公司需要一套简单的加密和解密系统来避免直接在互联网上传递明文信息。目前拟定了两种方案,一种是用使用凯撒密码,另一种是使用简单异或密码。设计并实现该系统。

我们还是先对凯撒密码和异或密码做一个简单的解释。

凯撒密码是一种最简单且最广为人知的加密技术。它是一种替换加密的技术,明文中的所有字母都在字母表上向后(或向前)按照一个固定数目进行偏移后被替换成密文。例如,当偏移量是3的时候,所有的字母A将被替换成D,B变成E,以此类推。这个加密方法是以恺撒的名字命名的,当年恺撒曾用此方法与其将军们进行联系。


简单异或密码是密码学中一种简单的加密算法,它按照如下原则进行运算:

\oplus 0 = A
\oplus A = 0
(A \oplus B) \oplus C = A \oplus (B \oplus C)
(B \oplus A) \oplus A = B \oplus 0 = B

其中\oplus逻辑异或(XOR)运算的符号。按这种逻辑,文本串行的每个字符可以通过与给定的密钥进行按位异或运算来加密。如果要解密,只需要将加密后的结果与密钥再次进行按位异或运算即可。

由于系统中存在两套加密和解密的方法,我们可以先为这两套方案设计一个公共的接口,这样在需要进行加密或解密时,只需要将接口类型实例化成具体的凯撒密码系统或简单异或密码系统就可以进行加密和解密了。也就是说,我们的密码系统有两种服务的方式,一种使用了凯撒密码另一种使用了简单异或密码,但是对调用者来说只需知道我们的系统中有加密和解密的方法,调用者并不关心具体的实现,这就是我们在上一章中提到的用服务的观点来审视多态。

在Java中可以使用interface关键字来定义接口,接口中的方法都是抽象方法,也就意味着实现了接口的类必须重写所有的抽象方法,否则该类仍然是抽象类。我们可以将接口视为一种约定,实现了接口的类必须实现接口中的方法;我们也可以将接口视为一种能力,实现了接口的类由于重写了接口中的方法就具备了接口所描述的能力;我们还可以将接口视为角色,一个类可以实现很多个接口,一个接口也可以被很多类实现,这就好比一个演员可以扮演多种角色,一个角色也可以由多个演员扮演。

该系统的代码如下:

package com.lovo.endec;

/**
 * 加解密系统的接口
 * @author 骆昊
 *
 */
public interface CipherSystem {

	/**
	 * 加密
	 * @param plainText 明文
	 * @return 密文
	 */
	public String encode(String plainText);
	
	/**
	 * 解密
	 * @param cipherText 密文
	 * @return 明文
	 */
	public String decode(String cipherText);
	
}

package com.lovo.endec;

/**
 * 凯撒密码系统
 * @author 骆昊
 *
 */
public class CaesarCipher implements CipherSystem {
	private int shift;	// 位移
	
	public CaesarCipher(int shift) {
		this.shift = shift;
	}
	
	@Override
	public String encode(String plainText) {
		plainText = plainText.toUpperCase();
		StringBuilder sb = new StringBuilder();
		for(int i = 0; i < plainText.length(); i++) {
			char currentChar = plainText.charAt(i);
			if(currentChar >= 'A' && currentChar <= 'Z') {
				sb.append((char)('A' + ((currentChar - 'A') + shift) % 26));
			}
			else {
				sb.append(currentChar);
			}
		}
		return sb.toString();
	}

	@Override
	public String decode(String cipherText) {
		cipherText = cipherText.toUpperCase();
		StringBuilder sb = new StringBuilder();
		for(int i = 0; i < cipherText.length(); i++) {
			char currentChar = cipherText.charAt(i);
			if(currentChar >= 'A' && currentChar <= 'Z') {
				sb.append((char)('A' + ((currentChar - 'A') - shift + 26) % 26));
			}
			else {
				sb.append(currentChar);
			}
		}
		return sb.toString();
	}

}

package com.lovo.endec;

/**
 * 简单异或密码系统
 * @author 骆昊
 *
 */
public class SimpleXORCipher implements CipherSystem {
	private int key;	// 秘钥
	
	public SimpleXORCipher(int key) {
		this.key = key;
	}

	@Override
	public String encode(String plainText) {
		StringBuilder cipherText = new StringBuilder();
		for(int i = 0; i < plainText.length(); i++) {
			cipherText.append((char)(plainText.charAt(i) ^ key));
		}
		return cipherText.toString();
	}

	@Override
	public String decode(String cipherText) {
		return encode(cipherText);
	}

}

package com.lovo.endec;

class CipherSystemTest {

	public static void showPlainText(CipherSystem sys, String text) {
		System.out.println(sys.decode(text));
	}
	
	public static void showCipherText(CipherSystem sys, String text) {
		System.out.println(sys.encode(text));
	}
	
	public static void main(String[] args) {
		String str1 = "I love you!";
		CipherSystem cs = new CaesarCipher(3);  // 使用凯撒密码
		showCipherText(cs, str1);
		String str2 = "L ORYH BRX!";
		showPlainText(cs, str2);
	}
}

package com.lovo.endec;

class CipherSystemTest {

	public static void showPlainText(CipherSystem sys, String text) {
		System.out.println(sys.decode(text));
	}
	
	public static void showCipherText(CipherSystem sys, String text) {
		System.out.println(sys.encode(text));
	}
	
	public static void main(String[] args) {
		String str1 = "I love you!";
		CipherSystem cs = new SimpleXORCipher(3);  // 使用简单异或密码
		showCipherText(cs, str1);
		String str2 = "J#oluf#zlv\"";
		showPlainText(cs, str2);
	}
}


大家可能已经注意到了,接口比抽象类更加抽象,接口本身也是不能实例化的,但是接口的使用却比抽象类更加灵活。在Java领域的经典著作《Effective Java》上讲到一条规则就是:接口优于抽象类。同时,该书还提到常量接口(定义一个接口来放置常量)是对接口不正确的使用方式。Java中的接口大致可以分为:单方法接口(接口中只有一个回调方法,例如:Runnable接口、ActionListener接口等)、标识接口(接口中没有任何方法,但是实现该接口却具备了某种能力,例如:Serializable接口、Cloneable接口等)、普通接口和常量接口。对接口的使用是Java程序设计中很有特点也是很有魅力的地方。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值