两个现实世界的例子
1.总开关
2.医院
3.文件加密(字符串拼接示范)
4.点餐
【例子描述】
房间有一个总开关,可以打开所有灯,而每一个灯都有自己的开关。在总开关中调用每个灯所对应的子开关。
package com.facade.switchs;
public interface ISwitch {
/**
* 默认的普通方法
*/
public default void openAll() {
on();
}
/**
* 抽象:打开所有开关
*/
public void on();
/**
* 抽象:关闭所有开关
*/
public void off();
}
package com.facade.switchs;
/**
* 外观类。
* 作用:在
* @author Feng
* 2018年8月8日上午10:25:25
*/
public class GeneralSwitchFacade implements ISwitch {
private Light[] lights;
private Fan[] fans;
public GeneralSwitchFacade() {
lights = new Light[4];
lights[0] = new Light("红色", "东边的");
lights[1] = new Light("绿色", "西边的");
lights[2] = new Light("蓝色", "南边的");
lights[3] = new Light("白色", "北边的");
fans = new Fan[4];
fans[0] = new Fan(0);
fans[1] = new Fan(1);
fans[2] = new Fan(2);
fans[3] = new Fan(3);
}
@Override
public void on() {
lights[0].on();
lights[1].on();
lights[2].on();
lights[3].on();
fans[0].on();
fans[1].on();
fans[2].on();
fans[3].on();
}
@Override
public void off() {
lights[0].off();
lights[1].off();
lights[2].off();
lights[3].off();
fans[0].off();
fans[1].off();
fans[2].off();
fans[3].off();
}
}
package com.facade.switchs;
/**
* 风扇,可以开和关。
* @author Feng
* 2018年8月8日下午7:32:39
*/
public class Fan {
private int index;
private Level[] levels = {Level.level1,Level.level2,Level.level3,Level.level4};
/**
* 构造方法中传入参数,控制风的级别。
* @param index
*/
public Fan(int index) {
this.index = index;
}
public void on() {
String message = getLevel(index);
if("".equals(message)) {
System.out.println("已经打开了风扇!");
} else {
System.out.println("已经打开了" + message + "的风扇!");
}
}
public void off() {
String message = getLevel(index);
if("".equals(message)) {
System.out.println("已经关闭了风扇!");
} else {
System.out.println("已经关闭了" + message + "的风扇!");
}
}
private String getLevel(int index) {
return levels[index].levelSize();
}
/**
* 级别
* @author Feng
* 2018年8月8日上午11:00:08
*/
private enum Level {
level1,
level2,
level3,
level4;
public String levelSize() {
if(this.equals(level1)) {
return "1级风";
}
if(this.equals(level2)) {
return "2级风";
}
if(this.equals(level3)) {
return "3级风";
}
if(this.equals(level4)) {
return "4级风";
}
return "";
}
}
}
package com.facade.switchs;
public class Light {
private String lightColor;// 灯光颜色。比如:红色光、蓝色光。
private String lightPosition;// 灯的位置。比如:东边的,西边的。
public Light() {}
public Light(String lightColor,String lightPosition) {
this.lightColor = lightColor;
this.lightPosition = lightPosition;
}
public void on() {
System.out.println(this.lightPosition + this.lightColor + "的灯打开了!");
}
public void off() {
System.out.println(this.lightPosition + this.lightColor + "的灯关闭了!");
}
}
package com.facade.switchs;
public class Test {
public static void main(String[] args) {
GeneralSwitchFacade facade = new GeneralSwitchFacade();
// 使用总开关,间接打开风扇和灯的开关。
facade.on();
// 使用总开关,间接关闭风扇和灯的开关。
facade.off();
}
}
【例子描述】
获取某一文件,对其使用一种加密技术,得到加密后的文件。其流程是:读取原文件——>加密——>保存加密文件。
期间,三个子系统各自独立,但是需要一个统一的外观类进行调度,而且不需要让他们之间产生关系。
package com.facade.encrypt;
public interface ICipherMachine {
/**
* 加密器接口中的默认加密方法:1.8之后。
* @param plainText
* @return
*/
public default String defaultEncrypt(String plainText) {
return "%6完的奇偶的及爱迪生去3群文28^"+plainText+"$#@%23当前12f5完全43@%@134";
}
public String encrypt(String plainText);
}
package com.facade.encrypt;
/**
* 文件加密类。
* @author Feng
* 2018年4月22日上午9:24:29
*/
public class CipherMachine implements ICipherMachine {
/**
* 获取到文件内容之后,简单的处理计划的文件内容。
* 对外提供,通过接口调用。
* @param plainText 读取到的文件内容
* @return 加密后的内容
*/
public String encrypt(String plainText) {
StringBuilder sb = new StringBuilder();
return sb.append("%6328^").append(plainText).append("$#@%134")
.append(subEncrypt(plainText)).toString();
}
/**
* 实现类中自己的一套实现方法。
* 隐藏私有。
* @param plainText
* @return
*/
private String subEncrypt(String plainText) {
//可以用append继续加工!
return plainText;
}
}
package com.facade.encrypt;
import java.io.IOException;
public class FileReader {
/**
* 从外部读取一个文件。
* @param fileNameSrc 源文件路径
* @return 读取到的文件内容,当读不到时,返回null
* @throws IOException 文件操作异常
*/
public String read(String fileNameSrc) throws IOException{
java.io.FileReader ioRead = new java.io.FileReader(fileNameSrc);
int num = 0;
char[] buff = new char[1024];
while((num = ioRead.read(buff))!= -1) {
ioRead.close();
System.out.println("已经成功获取到要加密的文件内容!");
return new String(buff,0,num);
}
ioRead.close();
return null;
}
}
package com.facade.encrypt;
import java.io.BufferedWriter;
import java.io.IOException;
/**
* 文件保存类。
* @author Feng
* 2018年4月22日上午9:26:36
*/
public class FileWriter {
/**
* 获取加密后的文件内容,将其保存到指定名字的文件中。
* @param encryptText 获取的加密后的文件内容。
* @param fileNameDes 保存的位置(文件名)
* @throws IOException 文件操作异常
*/
public void write(String encryptText, String fileNameDes) throws IOException {
java.io.FileWriter fw = null;
fw = new java.io.FileWriter(fileNameDes);
BufferedWriter bw = new BufferedWriter(fw);
bw.write(encryptText);
bw.flush();
bw.close();
System.out.println("文件已经加密!保存完毕!");
}
/**
* 测试方法!
* @param args main的参数
*/
public static void main(String[] args) {
String path = "C:\\Users\\Feng\\Desktop\\加密.txt";
try {
new FileWriter().write("123", path);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package com.facade.encrypt;
import java.io.IOException;
/**
* 可以写成单例。(我没这么写)
* @author Feng
*/
public class EncryptFacade {
private FileReader reader;
private ICipherMachine cipherMachine;
private FileWriter writer;
public EncryptFacade() {
reader = new FileReader();
cipherMachine = new CipherMachine();
writer = new FileWriter();
}
/**
* 文件加密方法。
* @param fileNameSrc 保存前,后文件路径。
* @param fileNameDes 文件名字
* @throws IOException
*/
public void fileEncrypt(String fileNameSrc,String fileNameDes) throws IOException {
//读取原来的文件。通过路径。
String plainText = reader.read(fileNameSrc);
//传入需要加密的字符串(文件内容),返回加密后的文件内容。
String encryptText = cipherMachine.encrypt(plainText);//调用实现类中的方法。
//String encryptText = cipherMachine.defaultEncrypt(plainText);//调用接口中的默认方法。
//将加密后的文件内容写入到指定的文件中。
writer.write(encryptText, fileNameDes);
}
}
package com.facade.encrypt;
import java.io.IOException;
/**
* 测试文件加密的外观的类。
* @author Feng
*/
public class Test {
public static void main(String[] args) {
EncryptFacade ef = new EncryptFacade();
String fileNameSrc = "C:\\Users\\Feng\\Desktop\\加密前.txt";
String fileNameDes = "C:\\Users\\Feng\\Desktop\\加密后.txt";
try {
ef.fileEncrypt(fileNameSrc, fileNameDes);
} catch (IOException e) {
e.printStackTrace();
}
}
}
【例子描述】
进入医院时,我们会发现医院都有前台!你需要挂号、咨询等操作,这里的前台能指引你去找到你需要的医生。找到前台几乎就能说是你找到路了。当你挂完号之后,就相当于你接收了前台的信息,找到了下家了,也就是说门面系统中的子系统被你找到 了。但是看医生时,医生所拥有的医术是医生本人的,并不是医院提供的,医院只管提供医生看病的场所罢了。可以简单理解为这时的医生的医术是被封装起来的方法,我们必须访问医生,才能调用该方法。【此类不做示范!】
【例子描述】
去一家饭店吃饭,首先遇到的是服务生,他在这里就充当着一个门面。服务生会介绍给你自家餐厅的服务,然后你就可以对这餐厅能提供的东西做到心里有数了。再之后,进行点餐,点完之后服务生提交到后厨,后厨就开始做菜,这一过程中,后厨是子系统,你通过访问服务生这个门面去调用后厨所拥有的方法!【此类不做示范!】
外观设计模式缺点:违背类开闭原则,当要增加新的子类系统时,需要修改外观类,这一点可以引用抽象外观类进行改进【例如我的文件加密案例中的引入接口,这时如果需要增加子系统只需要增加其实现类就可以了】