1. 为什么要进行分层
分层的目的是使软件具有结构性,便于开发、维护和管理。这正是软件开发希望达到的目的。将不同的功能模块独立开来,在改动一个层模块的时候,另一个层能不改变任何内容即可正常使用,这样可以方便代码的复用、替换。
2. 层与层之间的耦合度
软件设计的目标是使层与层之间、模块之间的高内聚、低耦合。耦合是指两个层或者模块之间的关联度。也就是说两者之间的相互影响程度,紧密关系程度。去掉两者之间的耦合性的过程就称为解耦。
3. 解耦
(1)面向接口编程——降低耦合性
作为java语言的一个重要内容——接口,在java代码的世界里扮演重要角色。使用接口可以达到高内聚低耦合的作用,是多态性的实现方式之一。提高代码的可扩展性。
不使用接口时候的编程,如在service层调用dao层的模块。代码如下:
publicclassUserService {
XMLUserDAOxmlUserDAO = new XMLUserDAO();
publicvoid add(User user){
xmlUserDAO.add(user);
}
}
不使用接口,这里的userDAO只能写死了,如果程序发生变动,则dao和service模块都必须进行改动。
使用接口编程的代码如下:
publicclassUserService {
IUserDAOuserDAO= newXMLUserDAO();//IUserDAO作为接口接收对象
publicvoid add(User user){
userDAO.add(user);
}
}
在此demo中,IUserDAO定义了dao所应该具有的方法,XMLUserDAO实现了此接口的add(User user)方法。如果需求发生变更,改用jdbc作为存储的数据库,则需要另写一个JDBCUserDAO实现IUserDAO的方法就可以扩展。缺点是需要修改XMLUserDAO为JDBCUserDAO。
(2)工厂模式解耦
publicclassUserService {
IUserDAO userDAO = (IUserDAO)DaoFactory.getDAO("xmlUserDAO");
publicvoid add(User user){
userDAO.add(user);
}
}
publicclassDaoFactory {
publicstatic Object getDAO(StringdaoName){
Objectobj = null;
if("xml".equals(daoName)){
obj= newXMLUserDAO();
}
return obj;
}
}
此工厂模式实现了dao与service层的解耦,缺点是需要传入字符串,去选择具体的实现类。
扩展:
工厂类一般都只需要一个对象即可,所以可以用单例模式创建。
字符串也可以采用xml或者properties文件配置的方式读入。
还可以在配置文件中写类的路径名,通过反射机制返回对象。
利用泛型作为参数传递,确定返回值dao的类型。
扩展之后代码如下:
publicclassDaoFactory {
privatestatic Properties properties = new Properties();
static{
//读取配置文件,获得接口对应的实现类
try {
properties.load(DaoFactory.class.getClassLoader().getResourceAsStream(""));
}catch(IOException e) {
thrownew RuntimeException(e);
}
}
privatestatic DaoFactory daoFactory = new DaoFactory();
private DaoFactory(){}
publicstatic DaoFactorygetInstance(){
returndaoFactory;
}
publicstatic <T> TgetDAO(Class<T> classType){
Stringkey = ();
StringdaoImplClass = properties.getProperty(key);
try {
return (T)Class.forName(daoImplClass).newInstance();
}catch(Exception e) {
thrownew RuntimeException(e);
}
}
}
publicclassUserService {
DaoFactorydaoFactory= DaoFactory.getInstance();
IUserDAOuserDAO= DaoFactory.getDAO(IUserDAO.class);
publicvoid add(User user){
userDAO.add(user);
}
}
(3)spring的ioc实现完全面向接口编程,完全解耦。在容器中实例化对象。
程序在运行过程中,如果需要调用另外一个对象时,无需在代码中创建被调用者,而是依赖外部的注入。