设计模式->结构型模式->外观模式(门面模式)

xiaoxiao2021-02-28  88

1.定义:要求一个子系统的内部与外部的通信只能通过一个统一的对象。此模式提供一个高层接口,使子系统更易使用

2.UML:

3.理论基础:封装,有可能涉及多态

4.涉及角色:

        门面角色:外界通过该角色访问子系统,该角色是子系统分友元角色,即该角色知道各个子系统对的职责以及功能。一般情况下该角色会将外界的请求委派到各个子系统中。可以看出该角色的主要职责由隔离子系统的访问,请求委派。该角色不建议涉及任何的逻辑。仅仅做隔离和委派

        子系统:一个类或者类的集合,业务的处理集中在各个子系统中。子系统并不知道门面的存在。对于子系统来说。门面也是一个客户端

5.优点

        1.减少客户端和子系统的依赖。如果客户端直接访问子系统,导致客户端强依赖于子系统。添加门面后客户端的依赖于门面。和子系统无关。实现解耦

2.提高灵活性,基于优点1,客户端依赖门面后,子系统内部的变不回影响到客户端。

3.提高安全性。由于外界是通过门面访问子系统的功能,只有在门面开通的情况下,外界才可以访问

6.缺点

       1. 违背开闭原则。没有办法通过扩展的方式修改门面,正能通过修改门面代码满足。如果我们将门面角色定义为抽象类或者接口。该缺点可以克服

7.使用场景

        1.在系统初期的设计阶段,层和层之间可以采用该种模式

        2.生产过程中子系统不断重构演化而越来越复杂,采用该模式提供提供一个简单的接口,减少之间的依赖

3.新系统需要接入老系统时可以为新系统提一个简单的访问点。减少新系统和老系统之间依赖。让新系统直接依赖于门面

4.子系统相对对立。外界对子系统的操作为黑箱操作。

5.降低风险扩散。降低个人代码对整个项目的影响。在子系统中开发,通过该模式为外界提供一个简单的访问接口

8.Code

抽象门面,定义了访问子系统的方法

public interface IFadace { public Object visitUserSystem(); public boolean visitAuditSystem(); public float visitFinanceSystem(); }具体门面

public class SubSystemFadace implements IFadace { private UserSystem us = new UserSystem(); private FinanceSystem fs = new FinanceSystem(); private AuditSystem as = new AuditSystem(); @Override public Object visitUserSystem() { return this.us.queryById(); } @Override public boolean visitAuditSystem() { return this.as.isEixst(); } @Override public float visitFinanceSystem() { return this.fs.turnover(); } }子系统

public class AuditSystem { public boolean isEixst() { System.out.println("记录存在"); return true; } } public class FinanceSystem { public float turnover(){ System.out.println("交易额:100W"); return 10000000; } } public class UserSystem { public Object queryById(){ //TODO something if(checkResut()) { throw new IllegalStateException("不存在"); } return new Object(); } private boolean checkResut(){ //TODO something return true; } }客户端

public class Client { public static void main(String[] args){ IFadace fadace = new SubSystemFadace(); fadace.visitAuditSystem(); fadace.visitFinanceSystem(); fadace.visitUserSystem(); } }注意事项:

1.一个子系统可以有多个门面。当后续门面类比较臃肿。我们可以按照功能将门面类进行拆分。

2.子系统可以提供不同的访问路径。在上面的例子中门面类提供了对各个系统的访问,现在只需要访问UserSystem

目前有两种方案:1.采用现有类不做任何扩展,但是这样会存在问题:将另外两系统的访问点暴露给客户端。2.新增门面类。该类中只提供访问UserSystem的接口,但是尽量采用系统原有的门面类。

public class UserSystemFadace { private IFadace fc = new SubSystemFadace(); public Object visitUserSystem() { return fc.visitUserSystem(); } }3.门面类不应该涉及任何的逻辑。在上面的例子中需要先访问UserSsytem,然后在访问其他的子系统

现在有如下几种方案1.采用目前系统中提供的API,将调用顺序委托给客户端 2.在现有的门面类中添加UserSystem子系统的访问,但是这样存在问题门面类涉及了具体的业务逻辑,门面类对象只是提供一个访问子系统的路径,不应该也不能参与具体的业务逻辑否则会产生一个倒依赖的问题子系统必须依赖门面才能被访问,违背单一职责,破坏了系统的封装性 3.建立封装类,封闭完成后提供给门面类

方案1:略

方案2:

public class SubSystemFadace implements IFadace { private UserSystem us = new UserSystem(); private FinanceSystem fs = new FinanceSystem(); private AuditSystem as = new AuditSystem(); @Override public Object visitUserSystem() { return this.us.queryById(); } @Override public boolean visitAuditSystem() { this.us.queryById(); return this.as.isEixst(); } @Override public float visitFinanceSystem() { return this.fs.turnover(); } } 方案3:

public class UASystemContext { private IFadace fc = new SubSystemFadace(); public boolean visitUASystem() { if(null != fc.visitUserSystem()){ return fc.visitAuditSystem(); } return false; } } public class SubSystemFadace implements IFadace { private UserSystem us = new UserSystem(); private FinanceSystem fs = new FinanceSystem(); private AuditSystem as = new AuditSystem(); private UASystemContext uasc = new UASystemContext(); @Override public Object visitUserSystem() { return this.us.queryById(); } @Override public boolean visitAuditSystem() { return this.uasc.visitUASystem(); } @Override public float visitFinanceSystem() { return this.fs.turnover(); } }

转载请注明原文地址: https://www.6miu.com/read-55789.html

最新回复(0)