作者爱谈话

明天是刚好来杭州的第二周,也是一个惬意的周五,很巧也是我的生日,将来的工作可能会很忙,还是会持续保持 sharing (原本昨天发的,然而还想欠缺欠缺就又拖了一天,哈哈。奥利给)

力求通过滑稽的模式解说各种设计模式的奇妙之处,带你设计模式从入门到入坑,做到他人加班,你加薪! Go

外观模式引入

王经理????:上课啦!林步动和郝漂亮到了没?

小林????:到了,经理。

小美????:我在这,经理。

王经理:好,那咱们来上课,明天咱们来讲一种类型为结构型的设计模式,就是外观模式,外观模式也叫做门面模式,从字面上了解就是,就是对外提供了一个对立的接口,用来拜访子系统中的一群接口,通过这个高层的接口,让这个子系统更容易被调用

小美:噢,经理你的意思是不是,外观模式就是实用于那种子系统越来越简单的状况,咱们能够减少外观模式使调用变的更简略,还能够缩小零碎依赖,涣散耦合

王经理:对,小美你了解的十分到位。

小林摸了摸头????:经理,我还是不太分明。

王经理:林步动,就晓得你不懂,接下来,咱们来 Coding 深刻了解一下。

关上你的 idea 和经理一起 Coding 吧!

外观模式 Coding

王经理:假如,咱们当初须要保护一个积分兑换礼物零碎

Leetcode - 算法题你值得领有

因为咱们主讲设计模式,所以简化业务过程,假如一个用户想要兑换物品,咱们得有一个物品对象,须要通过这几个步骤,校验积分、库存 -> 领取积分 -> 发货交付单号

  • ok,你的 idea 关上了么?来吧,Coding

设计一个物品对象,就一个简略的礼物名字就好了,记得 Alt + Insert 为这个对象退出 get/set/toString/结构等办法

    private String name;        public Gift(String name) {          this.name = name;      }        public String getName() {          return name;      }        public void setName(String name) {          this.name = name;      }        @Override      public String toString() {          return "Gift{" +                  "name='" + name + '\'' +                  '}';      }  }  

十分好,接下来设计一下 校验积分、库存的 Service? 为了简略,咱们间接传入 Gift ,而后间接输入校验通过,return true

    public Boolean isAvaliable(Gift gift) {          System.out.println("校验" + gift.getName() + "积分,库存通过");          return true;      }  }  

接下来,领取积分的 Service 是不是也是信手拈来,咱们间接传入 Gift ,而后间接输入领取胜利,return true

    public Boolean pay(Gift gift) {          System.out.println("领取" + gift.getName() + "胜利");          return true;      }  }  

ok,校验领取都通过,发货吧,老套路,传入 Gift,生成一个你喜爱的单号(就是这么随便),记得return单号 回去

    public String shipGift(Gift gift) {          System.out.println("正在运输" + gift.getName());          String shippingOrderNo = "666";          return shippingOrderNo;      }  }  

这么多子系统,你是不是很烦?所以外观模式的作用就体现进去了,咱们能够来做一个对立的 GiftService 去调用这些子系统。

      /**       * 因为咱们没有注入 Spring 环境,所以这里间接写个构造方法       */      private final PayService pointsPaymentService = new PayService();      private final CheckService checkService = new CheckService();      private final ShippingService shippingService = new ShippingService();        public void giftExchange(Gift gift) {  //      校验积分、库存          if (checkService.isAvaliable(gift)) {  //          领取积分              if (pointsPaymentService.pay(gift)) {  //              取得单号                  String orderNo = shippingService.shipGift(gift);                  System.out.println("物流曾经收回,订单号是 " + orderNo);              }          }      }  }  

一切都是如此的完满,赶快来写一个 Test 类测试一下吧。

public class Test {      public static void main(String[] args) {  //      生成一个礼物对象          Gift gift = new Gift(" iphone999 ");  //      没有 Spring 环境,间接 new GiftService. 如果在 Spring 环境中,间接注入 GiftService 就能够调用啦          GiftService giftService = new GiftService();            //      调用对立的接口          giftService.giftExchange(gift);      }  }  

run 一下?

发现,很完满的输入了咱们预计想实现的成果,这个 iphone 999 胜利的被收回了。

外观模式使用

王经理:接下来,咱们看下外观模式在框架中的使用,大家的 idea 双击 shift ,搜寻一下位于org.springframework.jdbc.support包中的 JdbcUtils 类(该类次要供外部应用的JDBC的通用办法)

JdbcUtils 类中的 closeConnection、closeStatement、closeResultSet、extractDatabaseMetaData 等办法就是外观类提供的调用子类的接口。

林步动,就你没开 idea,来,看大屏幕

public static void closeConnection(@Nullable Connection con) {      if (con != null) {          try {              con.close();          } catch (SQLException ex) {              logger.debug("Could not close JDBC Connection", ex);          } catch (Throwable ex) {              // We don't trust the JDBC driver: It might throw RuntimeException or Error.              logger.debug("Unexpected exception on closing JDBC Connection", ex);          }      }  }  

咱们拿 closeConnection 办法来举例,该办法的的入参 Connection 类位于 java.sql 包下,通过外观类的包装,客户端间接调外观类进行相应操作接口不须要间接调 java.sql 包下的子类。巧不巧,妙不妙,鼓掌~

外观模式总结

小林????:经理,外观模式是好奇妙啊,简化了好多的调用过程,我都不必理解深刻子系统了,这么好的设计模式有毛病吗?

经理:你小子,总算问道点上了,再好的设计模式都会有毛病,外观模式的毛病在于减少子系统,扩大子系统行为容易引入危险,不合乎开闭准则

经理:明天的课都听懂了吗?那留个问题给大家,听完这一课,你工作或者学习中有没有能够用外观模式优化的中央?外观模式你还能想到在其余的框架中的使用吗?

本节课代码地址: https://github.com/isysc1/desgin