简说设计模式——外观模式

一、什么是外观模式

  有些人可能炒过股票,但其实大部分人都不太懂,这种没有足够了解证券知识的情况下做股票是很容易亏钱的,刚开始炒股肯定都会想,如果有个懂行的帮帮手就好,其实基金就是个好帮手,支付宝里就有许多的基金,它将投资者分散的资金集中起来,交由专业的经理人进行管理,投资于股票、债券、外汇等领域,而基金投资的收益归持有者所有,管理机构收取一定比例的托管管理费用。

  其实本篇要说的这个设计模式就和这很有关系,由于当投资者自己买股票时,由于众多投资者对众多股票的联系太多,反而不利于操作,这在软件中就成为耦合性太高,而有了基金后,就变成众多用户只和基金打交道,关心基金的上涨和下跌,而实际上的操作确是基金经理人与股票和其它投资产品打交道,这就是外观模式。

  外观模式(Facade),为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。UML结构图如下:

 

  其中Facade是外观角色,也叫门面角色,客户端可以调用这个角色的方法,此角色知晓子系统的所有功能和责任,将客户端的请求代理给适当的子系统对象;Subsystem是子系统角色,可以同时拥有一个或多个子系统,每一个子系统都不是一个单独的类,而是一个类的集合,子系统并不知道门面的存在。

  1. 外观类

  这里我给出了四个Subsystem子系统,分别为A、B、C、D。

1 1 public class Facade { 2 2 3 //被委托的对象 3 4 SubSystemA a; 4 5 SubSystemB b; 5 6 SubSystemC c; 6 7 SubSystemD d; 7 8 8 9 public Facade() { 10 a = new SubSystemA(); 11 b = new SubSystemB(); 12 c = new SubSystemC(); 13 d = new SubSystemD(); 14 } 15 916 //提供给外部访问的方法 1017 public void methodA() { 18 this.a.dosomethingA(); 19 } 20 1121 public void methodB() { 22 this.b.dosomethingB(); 23 } 24 1225 public void methodC() { 26 this.c.dosomethingC(); 27 } 28 1329 public void methodD() { 30 this.d.dosomethingD(); 31 } 32 1433 }

   2. Subsystem子系统角色

  这里为了不过多赘述,只放上A的代码,其余子系统类似。

11 public class SubSystemA { 2 23 public void dosomethingA() { 4 System.out.println("子系统方法A"); 5 } 6 37 }

  3. Client客户端

1 1 public class Client { 2 2 3 public static void main(String\[\] args) { 4 Facade facade = new Facade(); 5 3 6 facade.methodA(); 4 7 facade.methodB(); 5 8 } 6 9 710 }

  运行结果如下:

  

二、外观模式的应用

  1. 何时使用

  • 客户端不需要知道系统内部的复杂联系,整个系统只提供一个“接待员”即可
  • 定义系统的入口

   2. 方法

  • 客户端不与系统耦合,外观类与系统耦合

   3. 优点

  • 减少了系统的相互依赖
  • 提高了灵活性。不管系统内部如何变化,只要不影响到外观对象,任你自由活动
  • 提高了安全性。想让你访问子系统的哪些业务就开通哪些逻辑,不在外观上开通的方法,你就访问不到

   4. 缺点

  • 不符合开不原则,修改很麻烦

   5. 使用场景

  • 为一个复杂的模块或子系统提供一个外界访问的接口
  • 子系统相对独立,外界对子系统的访问只要黑箱操作即可
  • 预防低水平人员带来的风险扩散

   6. 应用实例

  • 基金(用户只和基金打交道,实际操作为基金经理人与股票和其它投资品打交道)

 三、外观模式的实现

  我们就以开篇说的基金为例,来编写一下代码,熟悉外观模式的使用。UML图如下:

  1. 基金类(Fund)

  基金类,基金经理人通过该类作为中间交互者,可以接受投资者的资金,统一对股票、国债、房地产进行购买和赎回操作。

1 1 public class Fund { 2 2 3 Stock1 stock1; 3 4 Stock2 stock2; 4 5 Stock3 stock3; 5 6 NationalDebt1 nationalDebt1; 6 7 Realty1 realty1; 7 8 8 9 public Fund() { 10 stock1 = new Stock1(); 11 stock2 = new Stock2(); 12 stock3 = new Stock3(); 13 nationalDebt1 = new NationalDebt1(); 14 realty1 = new Realty1(); 15 } 16 917 //购买基金 1018 public void buyFund() { 19 stock1.buy(); 20 stock2.buy(); 21 stock3.buy(); 22 nationalDebt1.buy(); 23 realty1.buy(); 24 } 25 1126 //赎回基金 1227 public void sellFund() { 28 stock1.sell(); 29 stock2.sell(); 30 stock3.sell(); 31 nationalDebt1.sell(); 32 realty1.sell(); 33 } 34 1335 }

   2. 股票、国债、房地产类

  这里放一个股票作为示例,其余债券类似。内部由买入和卖出两种操作。

1 1 public class Stock1 { 2 2 3 //买股票 3 4 public void buy() { 5 System.out.println("股票1买入"); 4 6 } 5 7 6 8 //卖股票 7 9 public void sell() { 10 System.out.println("股票1卖出"); 11 } 12 813 }

  3. Client客户端

  用户通过该类对基金进行购买和赎回操作。

1 1 public class Client { 2 2 3 public static void main(String\[\] args) { 4 Fund fund = new Fund(); 5 3 6 //基金购买 4 7 fund.buyFund(); 5 8 System.out.println("-------------"); 6 9 //基金赎回 710 fund.sellFund(); 11 } 12 813 }

  运行结果如下:

  

  由此可见,外观模式十分的简单,我们只需在客户端购买和赎回即可,内部的任何操作都不需要我们关注,对于面向对象有一定基础的朋友,即使没有听说过外观模式,也完全有可能在很多时候使用它,因为它完美地体现了依赖倒转原则和迪米特法则的思想,所以是非常常用的模式之一。

  我们使用外观模式的情况有很多,比如经典的MVC三层架构,可以考虑在数据访问层和业务逻辑层、业务逻辑层和表示层的层与层之间简历外观Facade,降低耦合。对于复杂难以维护的老系统,直接去修改或扩展都可能产生很多问题,可以分两个小组,一个开发Facade与老系统的交互,另一个只要了解Facade接口,直接开发新系统调用这些接口即可。

   源码地址:https://gitee.com/adamjiangwh/GoF

本文转自 https://www.cnblogs.com/adamjwh/p/9048594.html,如有侵权,请联系删除。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )