外观设计模式(别名:门面设计模式)

两个现实世界的例子

1.总开关
2.医院
3.文件加密(字符串拼接示范)
4.点餐

总开关

【例子描述】
  房间有一个总开关,可以打开所有灯,而每一个灯都有自己的开关。在总开关中调用每个灯所对应的子开关。

【类图体现】
外观设计模式(别名:门面设计模式)_第1张图片

接口:ISwitch

package com.facade.switchs;

public interface ISwitch {
    /**
     * 默认的普通方法
     */
    public default void openAll() {
        on();
    }

    /**
     * 抽象:打开所有开关
     */
    public void on();

    /**
     * 抽象:关闭所有开关
     */
    public void off();
}

接口实现类:GeneralSwitchFacade

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();

    }

}

风扇类:Fan

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 "";

        }

    }

}

灯:Light

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 + "的灯关闭了!");
    }


}

测试总开关:Test

package com.facade.switchs;

public class Test {

    public static void main(String[] args) {

        GeneralSwitchFacade facade = new GeneralSwitchFacade();
        // 使用总开关,间接打开风扇和灯的开关。
        facade.on();
        // 使用总开关,间接关闭风扇和灯的开关。
        facade.off();
    }

}

总开关测试结果

外观设计模式(别名:门面设计模式)_第2张图片

简单的文件加密(字符串拼接示范)

【例子描述】
  获取某一文件,对其使用一种加密技术,得到加密后的文件。其流程是:读取原文件——>加密——>保存加密文件。
期间,三个子系统各自独立,但是需要一个统一的外观类进行调度,而且不需要让他们之间产生关系。

【类图体现】
外观设计模式(别名:门面设计模式)_第3张图片

加密器接口:ICipherMachine

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);
}

接口实现类:CipherMachine

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;
    }

}

外部读取:FileReader

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;
    }
}

保存文件:FileWriter

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();
        }
    }
}

门面类:EncryptFacade

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);

    }
}

测试类:Test

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();
        }
    }
}

加密成功:截图

外观设计模式(别名:门面设计模式)_第4张图片

医院的例子

【例子描述】
  进入医院时,我们会发现医院都有前台!你需要挂号、咨询等操作,这里的前台能指引你去找到你需要的医生。找到前台几乎就能说是你找到路了。当你挂完号之后,就相当于你接收了前台的信息,找到了下家了,也就是说门面系统中的子系统被你找到 了。但是看医生时,医生所拥有的医术是医生本人的,并不是医院提供的,医院只管提供医生看病的场所罢了。可以简单理解为这时的医生的医术是被封装起来的方法,我们必须访问医生,才能调用该方法。【此类不做示范!】

点餐的例子

【例子描述】
  去一家饭店吃饭,首先遇到的是服务生,他在这里就充当着一个门面。服务生会介绍给你自家餐厅的服务,然后你就可以对这餐厅能提供的东西做到心里有数了。再之后,进行点餐,点完之后服务生提交到后厨,后厨就开始做菜,这一过程中,后厨是子系统,你通过访问服务生这个门面去调用后厨所拥有的方法!【此类不做示范!】

结语

外观设计模式缺点:违背类开闭原则,当要增加新的子类系统时,需要修改外观类,这一点可以引用抽象外观类进行改进【例如我的文件加密案例中的引入接口,这时如果需要增加子系统只需要增加其实现类就可以了】

你可能感兴趣的:(设计模式&七大原则)