接口和面向接口编程

转自:接口和面向接口编程

在刚开始做开发的时候,我并不是很理解接口和面向接口编程在实际开发中的作用,比如:
  1)为什么需要 Service、DAO 的接口;
  2)为什么使用接口去引用依赖组件对象;
  3)为什么花费很大力气去设计对象工厂、对象容器,然后又把对象注入到依赖组件;

这些问题真是花了很长时间才搞清楚!

 

我们都知道,web 开发是分层的:控制层、业务层、数据层、实体类等,以业务层和数据层的依赖关系为例,通常可以使用三种方式来编写代码。

第一种:不编写接口,直接在业务层使用数据层的类来使用,简单粗暴、好理解

  数据层类 xxDao = new 数据层类();

第二种:编写接口和实现类,在业务层使用接口引用,但还是使用 new 关键字来实例化实现类对象,属于脱裤子放屁类型。

  数据层接口 xxDao = new 数据层实现类();

第三种:编写接口和实现类,在程序启动的时候使用“工厂”来管理对象,在业务层使用接口引用,然后从“工厂”获取需要的对象,或者使用框架注入,这里涉及到了多态和反射。

  数据层接口 xxDao = 工厂获取/注入;

 

在不使用 Spring 或者自定义对象工厂的时候,前两种方式都有可行,第二种方式可以为日后的架构设计升级提供一个接口规范,所以也是可以接受的。

在项目有了较大规模的时候,为了提高维护效率、实现组件之间的松耦合,我们会去设计“工厂”或者直接使用 Spring 来管理对象,这样做的好处在于:

在整体修改了数据层实现类实现方式的时候(如:把 hibernate 改为 mybatis),不需要去修改业务层的任何代码,只需要修改工厂配置文件即可实现组件的替换,因为任何一个符合“接口规范”的实现类对象都可以被注入到依赖该接口的业务类中去。

所以,我们有理由相信:反射、接口、多态是 Java 能够成为动态编程语言的最主要原因。

 

在本文中,我们暂时不去看 Web 项目的组件解耦方案,之前有过一篇文章写过自定义工厂的解耦方案,《多态和简单对象工厂》,Spring 放到以后再去讲解。

今天先用一个简单的例子介绍一下反射、接口是如何提高程序扩展性、可维护性的。

 

我们的例子是这样的:
  1)有 20 个业务需要进行监控,分属三个类型:A、B、C,每个类型的业务监控逻辑大致相同
  2)以后可能会增加 D、E 业务类型
  3)每个类型的业务数量也会随着项目的扩大而增加

我们需要设计一个方案,确保在业务类型、业务增加时可以快速的配置上线

 

第一种设计方案:

  1)编写A、B、C三个类型的监控类代码;
  2)在遍历全部业务时,分支结构判断业务类型,不同的类型创建不同的监控类对象,调用监控方法

  在我们的业务、业务类型增加时:需要增加相应的监控类;配置业务数据库;修改分支结构。

  如果有很多个业务类型,10个、20个,显然分支结构有些不美观。

  所以还有一种使用接口和反射实现的方案。

 

第二种设计方案:

  1)编写业务监控接口,有一个 doMinitor 方法;
  2)编写 A、B、C 三个类型的监控类,实现业务监控接口;
  3)在遍历全部业务时,通过业务类型获取到对应的业务监控实现类类型,实例化对象;
  4)通过业务监控接口的引用调用业务监控实现类的 doMinitor 方法,对业务进行监控

  在我们的业务、业务类型增加时:需要增加相应的监控类;配置业务数据库。

  所以,这个方案更加高大上。

 

我们简单看一下编码:

 

首先,Business 实体类用来保存业务信息

Business.java

复制代码
 1 public class Business {
 2 
 3     private String businessName;
 4     private String monitorPolicy;
 5 
 6     public Business() {
 7         super();
 8     }
 9 
10     public Business(String businessName, String monitorPolicy) {
11         super();
12         this.businessName = businessName;
13         this.monitorPolicy = monitorPolicy;
14     }
15 
16     public String getBusinessName() {
17         return businessName;
18     }
19 
20     public void setBusinessName(String businessName) {
21         this.businessName = businessName;
22     }
23 
24     public String getMonitorPolicy() {
25         return monitorPolicy;
26     }
27 
28     public void setMonitorPolicy(String monitorPolicy) {
29         this.monitorPolicy = monitorPolicy;
30     }
31 }
复制代码

 

接下来,编写监控接口和三种类型业务的实现类

Monitor接口

1 public interface Monitor {
2 
3     void doMonitor(Business business);
4 
5 }

 

MonitorA类

复制代码
1 public class MonitorA implements Monitor {
2 
3     @Override
4     public void doMonitor(Business business) {
5         System.out.println("监控业务类型A------" + business.getBusinessName());
6     }
7 }
复制代码

 

MonitorB类

复制代码
1 public class MonitorB implements Monitor {
2 
3     @Override
4     public void doMonitor(Business business) {
5         System.out.println("监控业务类型B------" + business.getBusinessName());
6     }
7 }
复制代码

 

MonitorC类

复制代码
1 public class MonitorC implements Monitor {
2 
3     @Override
4     public void doMonitor(Business business) {
5         System.out.println("监控业务类型C------" + business.getBusinessName());
6     }
7 }
复制代码

 

最后,是 RunMonitor 入口类

复制代码
 1 public class RunMonitor {
 2     
 3     private static List<Business> businessList = new ArrayList<Business>();
 4     
 5     static {
 6         businessList.add(new Business("业务01", "org.net5ijy.monitor.policy.MonitorA"));
 7         businessList.add(new Business("业务02", "org.net5ijy.monitor.policy.MonitorA"));
 8         businessList.add(new Business("业务03", "org.net5ijy.monitor.policy.MonitorA"));
 9         businessList.add(new Business("业务04", "org.net5ijy.monitor.policy.MonitorA"));
10         businessList.add(new Business("业务05", "org.net5ijy.monitor.policy.MonitorA"));
11         businessList.add(new Business("业务06", "org.net5ijy.monitor.policy.MonitorA"));
12         businessList.add(new Business("业务07", "org.net5ijy.monitor.policy.MonitorB"));
13         businessList.add(new Business("业务08", "org.net5ijy.monitor.policy.MonitorB"));
14         businessList.add(new Business("业务09", "org.net5ijy.monitor.policy.MonitorB"));
15         businessList.add(new Business("业务10", "org.net5ijy.monitor.policy.MonitorB"));
16         businessList.add(new Business("业务11", "org.net5ijy.monitor.policy.MonitorB"));
17         businessList.add(new Business("业务12", "org.net5ijy.monitor.policy.MonitorB"));
18         businessList.add(new Business("业务13", "org.net5ijy.monitor.policy.MonitorC"));
19         businessList.add(new Business("业务14", "org.net5ijy.monitor.policy.MonitorC"));
20         businessList.add(new Business("业务15", "org.net5ijy.monitor.policy.MonitorC"));
21         businessList.add(new Business("业务16", "org.net5ijy.monitor.policy.MonitorC"));
22         businessList.add(new Business("业务17", "org.net5ijy.monitor.policy.MonitorC"));
23         businessList.add(new Business("业务18", "org.net5ijy.monitor.policy.MonitorC"));
24         businessList.add(new Business("业务19", "org.net5ijy.monitor.policy.MonitorC"));
25         businessList.add(new Business("业务20", "org.net5ijy.monitor.policy.MonitorC"));33     }
34 
35     public static void main(String[] args) {
36 
37         for (Business business : businessList) {
38             String policyName = business.getMonitorPolicy();
39             try {
40                 Class<?> cls = Class.forName(policyName);
41 
42                 Monitor monitor = (Monitor) cls.newInstance();
43 
44                 monitor.doMonitor(business);
45 
46             } catch (ClassNotFoundException e) {
47                 e.printStackTrace();
48             } catch (InstantiationException e) {
49                 e.printStackTrace();
50             } catch (IllegalAccessException e) {
51                 e.printStackTrace();
52             }
53         }
54     }
55 }
复制代码

 

项目结构如下:

 

 

 

 

 

过了一段时间,增加了业务类型 D、E,增加了五个业务,分属 D、E,可以使用下面方式进行扩展:

 

MonitorD类

复制代码
1 public class MonitorD implements Monitor {
2 
3     @Override
4     public void doMonitor(Business business) {
5         System.out.println("监控业务类型D------" + business.getBusinessName());
6     }
7 }
复制代码

 

MonitorE类

复制代码
1 public class MonitorE implements Monitor {
2 
3     @Override
4     public void doMonitor(Business business) {
5         System.out.println("监控业务类型E------" + business.getBusinessName());
6     }
7 }
复制代码

 

项目结构如下:

 

posted @ 2019-08-02 10:28  feiquan  阅读(390)  评论(0编辑  收藏  举报
如果是此文是转载文章,本人会附上转载链接,此篇文章的版权归原创作者所属,如果侵权请与我联系,我会删除此文。

若没有标明转载链接,此篇文章属于本人的原创文章,其版权所属:
作者:feiquan
出处:http://www.cnblogs.com/feiquan/
版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
大家写文都不容易,请尊重劳动成果~ 这里谢谢大家啦(*/ω\*)