我们都知道在java中有(OCP:Open/Closed Principle)原则,对扩展开放,对修改关闭.但是在实际中如果使用传统的开发方式很难做到这一点,比如如下场景:web service dao层中增加用户业务逻辑上有变化,如何才能做到不改变原代码的情况下,对新增功能进行扩展呢?

这里就需要用到java的面向接口编程.接下来将通过这一案例对面向接口编程做演示.

首先:原有环境如下图

原环境.JPG

service层(模拟功能):

package com.xfz.service;
public class UserService1 {
public void addUser(){
System.out.println("增加用户");
}
}
web层(模拟功能测试)
package com.xfz.web;
import com.xfz.service.UserService1;
public class UserTest {
public static void main(String[] args) {
UserService1 user = new UserService1();
user.addUser();
}
}

现在业务层用户功能更新,由于不能在原代码上进行修改,所以这里在业务层新建类UserService2来进行模拟:

02.JPG

service层UserService2代码(模拟功能更新):

package com.xfz.service;
public class UserService2 {
public void addUser(){
System.out.println("增加用户新功能");
}
}

现在业务层用户功能更新,由于不能在原代码上进行修改,所以这里在业务层新建类UserService2来进行模拟:

到这里问题就来了:现在要实现UserService2的新功能,如果使用传统方式在web层UserTest下进行创建UserService2类对象调用方法,那么今后每次增加新功能都将重复进行创建新对象调用新方法(功能),而这种对原代码进行修改的方式不符合java 开闭原则,对扩展开放对修改关闭.所以这里我们将使用面向接口的方式来对web层service层dao层的代码进行耦合性分离,实现新增功能无需修改原代码同样也能实现新增功能.

思想:面向接口编程,解开三层耦合性

步骤:

1.创建UserInterface接口

图片.png

UserInterface接口代码:
package com.xfz.service;
public interface UserInterface {
public void addUser();
}

2.UserService1和UserService2实现UserInterface 接口

图片.png

UserService1代码:

package com.xfz.service.impl;
import com.xfz.service.UserInterface;
public class UserService1 implements UserInterface{
public void addUser(){
System.out.println("增加用户");
}
}

UserService2代码:

package com.xfz.service.impl;
import com.xfz.service.UserInterface;
public class UserService2 implements UserInterface{
public void addUser(){
System.out.println("增加用户新功能");
}
}

3.在项目根目录src下创建bean.properties配置文件

图片.png

bean.properties配置文件内容:
#bean工厂的配置,键是接口名=值是该接口的实现类
UserInterface=com.xfz.service.impl.UserService2

4.创建工具类(传入接口生产实现类)

具类BeanFactory代码:
package com.xfz.utils;
import java.util.ResourceBundle;
public class BeanFactory {
/**
* 接收接口,返回他的实现类对象
* 接收的是接口的class对象
* 任意类的class对象都是Class对象
*/
public static T getInstance(Class clazz ) {
//读取配置文件,获取接口实现类的类名,反射创建对象
//获取出传递的接口名字吗
String simpleName = clazz.getSimpleName();
ResourceBundle resourceBundle = ResourceBundle.getBundle("bean");
//传递接口名作为键,获取值,是实现类的全名
String className = resourceBundle.getString(simpleName);
T t = null;
//反射创建对象
try {
Class cla = Class.forName(className);
//创建该类的对象,返回Object
t = (T) cla.newInstance();
}catch (Exception ex){ex.printStackTrace();}
return t;
}
}

5.web层代码使用接口接收接口实现类对象(功能块下所有功能)

图片.png
web层UserTest代码
import com.xfz.service.UserInterface;
import com.xfz.service.impl.UserService1;
import com.xfz.utils.BeanFactory;
public class UserTest {
public static void main(String[] args) {
// UserService1 user = new UserService1();
// user.addUser();
UserInterface user = BeanFactory.getInstance(UserInterface.class);
user.addUser();
}
}

右键运行后,成功执行UserService2新增功能.并且今后扩展相关功能,原代码无需在改变,只需在将新功能类在配置文件进行配置即可.

Spring框架基本也是同上原理,不过现在注解开发也是占主流,但是理解面向接口编程对于今后的知识拓展还是很有帮助的.

以上就是本次面向接口编程案例的演示.有问题欢迎在评论区进行讨论.O(∩_∩)O