JAVA设计模式 - 外观模式


  本文参考自书籍《JAVA设计模式》

什么是外观模式

  外观模式是一种使用频率非常高的结构性设计模式,它通过引入一个外观角色来简化客户端与子系统之间的交互。为复杂的子系统提供一个统一的入口,使子系统和客户端之间耦合度降低。

外观模式:为子系统中的一组接口提供一个统一的入口。外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

外观模式的结构

在这里插入图片描述

外观模式的代码示例

子系统1

package facade;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;


/**
 * 文件读取功能
 *
 * @author zhao.hualuo
 * Create at 2021/12/24
 */
public class FileReader {

    private static final Logger LOGGER = LoggerFactory.getLogger(FileReader.class);

    /**
     * 读取本地文件
     *
     * @param fileName 文件名全路径
     * @return 文件内容
     */
    public String read(String fileName) {
        StringBuilder stringBuilder = new StringBuilder();
        try {
            List<String> fileLines = Files.readAllLines(Paths.get(fileName));
            for (String fileLine : fileLines) {
                stringBuilder.append(fileLine).append("\n");
            }
        } catch (FileNotFoundException exception) {
            LOGGER.error("文件不存在");
        } catch (IOException exception) {
            LOGGER.error("解析文件失败", exception);
        }
        LOGGER.info("读取文件,获取明文:{}", stringBuilder);
        return stringBuilder.toString();
    }
}

子系统2

package facade;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;

/**
 * 文件写入功能
 *
 * @author zhao.hualuo
 * Create at 2021/12/27
 */
public class FileWriter {

    private static final Logger LOGGER = LoggerFactory.getLogger(FileWriter.class);

    /**
     * 写入文件
     *
     * @param fileName 文件名
     * @param lines 内容
     * @throws IOException 异常
     */
    public void writeFile(String fileName, String lines) throws IOException {
        LOGGER.info("写入文件:{} {}", fileName, lines);
        if (!Files.exists(Paths.get(fileName))) {
            Files.createFile(Paths.get(fileName));
        }
        Files.write(Paths.get(fileName), lines.getBytes(StandardCharsets.UTF_8));
    }
}

子系统3

package facade;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Optional;

/**
 * MD5加密工具类
 *
 * @author zhao.hualuo
 * Create at 2021/12/24
 */
public class Md5EncryptionUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(Md5EncryptionUtil.class);

    private static final String KEY_MD5 = "MD5";

    public String encrypt(String baseString) throws Exception {
        byte[] digest = null;
        try {
            MessageDigest md5 = MessageDigest.getInstance(KEY_MD5);
            digest = md5.digest(baseString.getBytes(StandardCharsets.UTF_8));
        } catch (NoSuchAlgorithmException e) {
            LOGGER.error("未找到该加密算法", e);
        }
        return Optional.ofNullable(digest)
                .map(param -> new BigInteger(1, param).toString(16))
                .orElseThrow(() -> new Exception("加密失败"));
    }
}

子系统4

package facade;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

/**
 * 安全散列算法(SHA)
 *
 * @author zhao.hualuo
 * Create at 2021/12/27
 */
public class ShaEncryptionUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(ShaEncryptionUtil.class);

    private static final String KEY_SHA = "SHA";

    /**
     * SHA加密(比MD5更安全)
     *
     * @param data 需要加密的数据
     * @return 加密后
     * @throws NoSuchAlgorithmException 异常
     */
    public String encryptSha(String data) throws NoSuchAlgorithmException {
        MessageDigest instance = MessageDigest.getInstance(KEY_SHA);
        instance.update(data.getBytes(StandardCharsets.UTF_8));
        return Arrays.toString(instance.digest());
    }
}

外观类1

package facade;

/**
 * MD5加密外观类
 *
 * @author zhao.hualuo
 * Create at 2021/12/27
 */
public class Md5EncryptFacade extends AbstractEncryptFacade {

    private static final String SPLIT = "\\.";

    /** MD5加密工具类 */
    private final Md5EncryptionUtil md5EncryptionUtil;

    /** 文件写入 */
    private final FileWriter fileWriter;

    /** 文件读取 */
    private final FileReader fileReader;

    public Md5EncryptFacade() {
        fileWriter = new FileWriter();
        fileReader = new FileReader();
        md5EncryptionUtil = new Md5EncryptionUtil();
    }

    /**
     * MD5文件加密
     *
     * @param fileName 文件全路径
     * @throws Exception 异常
     */
    @Override
    public void fileEncrypt(String fileName) throws Exception {
        String content = fileReader.read(fileName);
        String encrypt = md5EncryptionUtil.encrypt(content);
        fileWriter.writeFile(convertToResultFileName(fileName), encrypt);
    }

    private String convertToResultFileName(String fileName) {
        String[] split = fileName.split(SPLIT);
        split[0] += "-result";
        return String.join(".", split);
    }
}

外观类2

package facade;

/**
 * SHA加密外观类
 *
 * @author zhao.hualuo
 * Create at 2021/12/27
 */
public class ShaEncryptFacade extends AbstractEncryptFacade {

    private static final String SPLIT = "\\.";

    /** SHA加密工具类 */
    private final ShaEncryptionUtil shaEncryptionUtil;

    /** 文件写入 */
    private final FileWriter fileWriter;

    /** 文件读取 */
    private final FileReader fileReader;

    public ShaEncryptFacade() {
        fileWriter = new FileWriter();
        fileReader = new FileReader();
        shaEncryptionUtil = new ShaEncryptionUtil();
    }

    /**
     * MD5文件加密
     *
     * @param fileName 文件全路径
     * @throws Exception 异常
     */
    @Override
    public void fileEncrypt(String fileName) throws Exception {
        String content = fileReader.read(fileName);
        String encrypt = shaEncryptionUtil.encryptSha(content);
        fileWriter.writeFile(convertToResultFileName(fileName), encrypt);
    }

    private String convertToResultFileName(String fileName) {
        String[] split = fileName.split(SPLIT);
        split[0] += "-result";
        return String.join(".", split);
    }
}

抽象外观类

package facade;

/**
 * 抽象外观类
 *
 * @author zhao.hualuo
 * Create at 2021/12/27
 */
public abstract class AbstractEncryptFacade {

    /**
     * 文件加密
     *
     * @param fileName 文件全路径
     * @throws Exception 异常
     */
    public abstract void fileEncrypt(String fileName) throws Exception;
}

客户端

package facade;

/**
 * 客户端
 *
 * @author zhao.hualuo
 * Create at 2021/12/27
 */
public class Client {

    public static void main(String[] args) throws Exception {
        AbstractEncryptFacade md5Facade = new Md5EncryptFacade();
        md5Facade.fileEncrypt("D:\\Documents\\person\\designPattern\\md5Test.txt");
        System.out.println("MD5加密完成");

        AbstractEncryptFacade shaFacade = new ShaEncryptFacade();
        shaFacade.fileEncrypt("D:\\Documents\\person\\designPattern\\shaTest.txt");
        System.out.println("SHA加密完成");
    }
}

外观模式的优缺点

外观模式优点

  1. 它对客户端屏蔽了子系统组件,减少了客户端需要处理的子对象数目,并使子系统使用起来更加容易,通过引入外观模式,客户端代码将变的很简单,与之关联的对象也很少。
  2. 它实现了子系统和客户端之间的松耦合关系,这使得子系统的变化不会影响到调用它的客户端,只需要调整外观类即可。
  3. 一个子系统的修改对其他子系统无影响,而且子系统内部变化也不会影响到外观对象。

外观模式缺点

  1. 不能很好的限制客户端直接使用子系统类,如果客户端对访问子系统类做太多的限制就减少了可变性和灵活性。
  2. 如果设计不当,增加新的子系统可能需要修改外观内的元外卖,违背了开闭原则。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值