从新生入学流程的例子看门面模式

门面模式说明

门面模式是一种构造型设计模式,能为程序库、框架或其他复杂类提供一个简单接口

优点

  • 你可以让自己代码独立于复杂的子系统

缺点

  • 外观类可能会成为程序中与所有类都耦合的上帝对象
  • 如果设计不当,当子系统新增功能时,可能会需要修改门面类,这样就违背了开闭原则

例子

接下来我们通过这个新生入学流程的例子来体会一下门面模式的有点与缺点

定义门面

我们定义一个学校的门面,这个门面中声明了入学这个方法

/**
 * 学校
 * @author skyline
 */
public interface SchoolFacade {

    /**
     * 新生入学
     *
     * @param student
     */
    void entrance(Student student);
}

提供具体的实现类与具体的逻辑

/**
 * 教务处
 * @author skyline
 */
@Service
public class DeanOfficeService {

    void checkIn(Student student) {
        System.out.println(student.getName() + "【" + student.getMajor() + "】来教务处报道了");
    }
}
/**
 * 宿舍
 * @author skyline
 */
@Service
public class DormitoryService {

    void checkIn(Student student) {
        System.out.println(student.getName() + "【" + student.getMajor() + "】来宿舍阿姨这里报道了,领走了宿舍钥匙");
    }
}
/**
 * 班主任
 * @author skyline
 */
@Service
public class HeadmasterService {

    void checkIn(Student student) {
        System.out.println(student.getName() + "【" + student.getMajor() + "】来班主任这里报道了,班主任给了一些宣传手册");
    }
}
/**
 * 辅导员
 * @author skyline
 */
@Service
public class InstructorService {

    void checkIn(Student student) {
        System.out.println(student.getName() + "【" + student.getMajor() + "】来辅导员这里报道了,辅导员给讲了一些注意事项");
    }
}
/**
 * 后勤处
 * @author skyline
 */
@Service
public class LogisticsService {

    void checkIn(Student student) {
        System.out.println(student.getName() + "【" + student.getMajor() + "】来后勤处报道了,领走了饭卡");
    }
}

@Service
public class SchoolServiceImpl implements SchoolFacade {

    @Autowired
    private DeanOfficeService deanOfficeService;
    @Autowired
    private DormitoryService dormitoryService;
    @Autowired
    private HeadmasterService headmasterService;
    @Autowired
    private InstructorService instructorService;
    @Autowired
    private LogisticsService logisticsService;

    @Override
    public void entrance(Student student) {
        //先来教务处报道
        deanOfficeService.checkIn(student);
        //然后去后勤处报道
        logisticsService.checkIn(student);
        //再去班主任这里报道
        headmasterService.checkIn(student);
        //再来辅导员这里报道
        dormitoryService.checkIn(student);
        //最后去宿管阿姨这里报道
        instructorService.checkIn(student);
    }
}

使用门面

@Configuration
@ComponentScan("com.example.designpatterns.faced")
public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Main.class);
        SchoolFacade schoolFacade = applicationContext.getBean(SchoolFacade.class);
        Student student = new Student();
        student.setName("张三");
        student.setMajor("数学系");
        schoolFacade.entrance(student);
    }
}

结果

在这里插入图片描述

总结

  1. 从上面的例子中可以很明显的感受到,当我们使用门面模式时,调用起来非常的简单。从SchoolServiceImpl 中可以看到,新生入学的流程是一个需要多个模块组合产生的功能,但是如果我们使用门面模式,在代码中只依赖SchoolFacade ,调用方只通过一行代码schoolFacade.entrance(student)就完成了新生入学的操作,非常的简洁。
  2. 门面模式在一定程度上很好的完成了解耦的工作,客户端调用时,只依赖门面即可,不需要了解门面的内部实现逻辑,如果新生入学的流程发生变化,那也是修改SchoolServiceImpl,客户端的调用是不需要改动的。
  3. 同时门面的实现类SchoolServiceImpl可能成为一个上帝对象。为了实现门面声明的功能不得不依赖很多很多的类,这使得SchoolServiceImpl的维护将变得复杂。
  4. 门面模式是一把双刃剑,在对外提供便捷接口的同时,对内也会变得复杂,需要用心设计。

常见的门面模式

  1. 最最常见的就是Logger了。我们常见的Log4jLog4j2LogBack都是日志框架,他们都有自己独立的api。但是我们在开发中都是依赖org.slf4j.Loggerorg.slf4j.LoggerFactory的。这样就算是切换了日志框架,对业务代码也没有影响。这是一种非常好的解耦方式。
  2. 在spring中有一个非常常用的接口ApplicationContext,这个接口也是门面模式。这个接口组合了EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver的功能。

    很多时候,当我们开发时,为了保持单一职责原则会拆分出很多很多的接口出来。这样开发的代码可复用性强,可维护性好。唯一的缺点就是其他的开发人员需要记住很多接口。所以才会有了像ApplicationContext这样的接口,ApplicationContext整合了很多spring的接口提供了一站式的服务能力。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值