设计模式之外观模式

外观模式

概述

外观模式可以为互相关联在一起的错综复杂的类整理出高层接口,其中Facade角色可以让系统对外只有一个简单的API。而且Facade角色还会考虑到系统内部各个类之间的责任关系和依赖关系,按照正确的顺序调用各个类。

外观模式中的Facade角色其实可以看成一个中间件,举一个比较熟悉的例子,在没有学习MyBatisPlus、MyBatis之前,我们对数据库的访问是使用JDBC的方式,而MyBatisPlus、MyBatis将内部调用的方法或类,整理出一个简单的API供我们使用。

示例程序

在示例程序中,我们编写简单的web页面

UML类图

名字说明
Database从邮件地址中获取用户名的类
HtmlWriter编写HTML文件的类
PageMaker根据邮件地址编写该用户的web页面
Test测试程序类

在这里插入图片描述

代码实现

Database

此类主要用于读取文件,生成properties

public class Database {
    private Database() {//禁止外部使用new
    }

    /**
     * 获取配置文件
     * @param dbName
     * @return
     */
    public static Properties getProperties(String dbName) throws FileNotFoundException {
        File file =  ResourceUtils.getFile("classpath:" + dbName + ".txt");
        Properties properties = new Properties();
        try {
            properties.load(new FileInputStream(file));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return properties;
    }
}

maildata.txt

yellowstar@qq.com=Yellow Star
max@qq.com=Max

HtmlWriter

此类主要用于编写html文件

public class HtmlWriter {
    private Writer writer;

    public HtmlWriter(Writer writer) {
        this.writer = writer;
    }

    /**
     * 输出标题
     * @param title
     */
    public void title(String title) throws IOException {
        writer.write("<html>");
        writer.write("<head>");
        writer.write("<title>" + title + "</title>");
        writer.write("</head>");
        writer.write("<body>\n");
        writer.write("<h1>" + title + "</h1>" + "\n");
    }

    /**
     * 输出段落
     * @param msg
     */
    public void paragraph(String msg) throws IOException {
        writer.write("<p>" + msg + "</p>\n");
    }

    /**
     * 输出超链接
     * @param href
     * @param caption
     * @throws IOException
     */
    public void link(String href,String caption) throws IOException {
        paragraph("<a href=\"" + href + "\">" + caption + "</a>");
    }

    /**
     * 输出邮件地址
     * @param mailaddr
     * @param username
     */
    public void mailto(String mailaddr,String username) throws IOException {
        link("mailto:" + mailaddr,username);
    }

    public void close() throws IOException {
        writer.write("</body>");
        writer.write("</html>\n");
        writer.close();
    }
}

PageMaker

将Database和HtmlWriter包装成一个接口,提供给外部使用

public class PageMaker {
    private PageMaker() {//禁止new
    }

    public static void makeWelcomePage(String mailaddr,String filename){
        try {
            Properties maildata = Database.getProperties("maildata");
            String username = maildata.getProperty(mailaddr);
            HtmlWriter htmlWriter = new HtmlWriter(new FileWriter(filename));
            htmlWriter.title("Welcome to" + username + "`s page!");
            htmlWriter.paragraph(username + " 欢迎来到" + username + "的主页");
            htmlWriter.mailto(mailaddr,username);
            htmlWriter.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

test

@SpringBootTest
class Practice1300ApplicationTests {
    @Test
    void contextLoads() {
        PageMaker.makeWelcomePage("yellowstar@qq.com","welcome.html");
    }
}

在这里插入图片描述

登场角色

  • Facade

    Facade角色是代表构成系统的许多其他角色的简单窗口,Facade角色向系统外部提供高层接口API。在示例程序中由PageMaker扮演该角色

  • 构成系统的许多其他角色

    这些角色各自完成各自的工作,它们并不知道Facade角色,由Facade角色调用它们进行工作。在示例程序中由Database、HtmlWriter扮演该角色

习题

为了能够方便的对程序进行拓展和改善,作为设计者,我们想让pagemaker包外部的程序只能使用PageMaker类,而不能使用Database和HtmlWriter,如何改善该程序?(PageMaker、Database、HtmlWriter同属于pagemaker包)

将Database、HtmlWriter类前面的public去掉即可

class Database{}
class HtmlWriter{}

总结

  • 外观模式可以让复杂的东西看起来简单,复杂的东西指的是在后台工作的这些类之间的关系和它们的使用方法,使用外观模式可以让我们不必在意这些复杂的东西。

  • 接口变少了,意味着程序与外部的关联关系弱化了,这样更容易使我们的包作为组建被复用。

  • 在设计类时,我们需要考虑将哪些方法的可见性设置为public,如果公开方法过多,会导致累的内部的修改变得困难。字段也是一样,如果不小心将某个字段公开出去,那么其他的类可能会读取或修改该字段。

  • 在设计包时,也需要考虑类的可见性,如习题,我们不希望别人按照它们的思维修改内部的类的逻辑。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值