设计模式设计原则之迪米特原则

97 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第4天,点击查看活动详情

简介

迪米特原则软件行业内的含义是如果两个软件实体(模块,类,方法)不需要直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用。其目的是降低类之间的耦合度,提高模块的相对独立性,避免在修改一个软件实体时影响到它的调用方。说白了终极目的还是高内聚、低耦合的思想。

那我理解用一句话概括:尽量少和陌生人说话!

那问题来了,哪些是陌生人,同事算吗?邻居算吗?隔壁班的妹纸算吗?且听我一一道来。

朋友:出现在成员变量,方法输入,输出参数中的类称为成员朋友类。

陌生人:局部变量中的类则不是直接的朋友。

这样看来也是比较好理解的,成员变量、输入、输出都是朋友,而且这些朋友往往是出现在比较醒目的位置:成员变量经常在类的头部定义,而输入输出也是在方法的一头一尾定义,即使有改动也是非常容易找到的。相反在一个方法中的局部变量是比较难找的,因为方法的每一行都可能定义。

应用

就拿我们最熟悉的用户角色权限来举例子:

public class User {
    /**
     * 同过用户id查询其拥有的角色
     * @return
     */
    public List<Permission> getPermisionListByUser(Integer userId) {
        Role role = new Role();
        Integer roleId = role.getRoleIdByUserId(userId);
        Permission permissionService = new Permission();
        return permissionService.getPermissionListByRole(roleId);
    }
}
public class Role {
    public Integer getRoleIdByUserId(Integer userId) {
        return Integer.MAX_VALUE;
    }
}
public class Permission {

    /**
     * 通过角色Id查询此角色的权限
     * @param roleId
     * @return
     */
    public List<Permission> getPermissionListByRole(Integer roleId) {
        ArrayList<Permission> permList = new ArrayList<>();
        permList.add(new Permission());
        return permList;
    }
}

以上3个类实现了通过用户id查询用于所有的权限。通过在UserService中的getPermisionListByUser实现了此功能。没毛病,但是违反了迪米特原则,因为在此方法中出现了RoleService和PermissionService这2个陌生人

下面我们开始改造,干掉陌生人的出现。

public class User {
    /**
     * 同过用户id查询其拥有的角色
     * @return
     */
    public List<Permission> getPermisionListByUser(Integer userId, Role role) {
        return role.getPermissionListByUserId(userId);
    }
}
public class Role {
    public List<Permission> getPermissionListByUserId(Integer userId) {
        ArrayList<Permission> permList = new ArrayList<>();
        permList.add(new Permission());
        return permList;
    }
}
public class Permission {
}

如此,完美遵循迪米特原则。

总结

我觉得迪米特法则不是一定要按照原则强制执行的,在实际开发中不可能不引入其他类型的局部变量,但是咱们要尽可能地少用,不是不和陌生人说话,而是要尽量少说。

1、在类功能的划分上应该尽可能地减少耦合,功能分离,他们之间的耦合越小,越利于实现可复用

2、迪米特法则的要求其实对代码整洁也是很有帮助的,少引入局部变量肯定就要求代码有更多更好的封装。方法的长度也能得到有效控制

3、不暴露类的属性成员,而应该提供相应的访问器(get、set)

4、在类的结构设计上,尽量降低类成员的访问权限