接口隔离原则涉及几个类 - 如何正确设计?

时间:2016-06-14 02:41:37

标签: java oop

假设我在系统中有两个类:

public class User {
    public int getId() {
        // implementation
    }

    // other methods
}

public class Room {
    public int getId() {
        //implementation
    }

    public void addUser(User user) {
        int userId = user.getId();
        // uses userId
    }

    // other methods
}

然后我意识到这些类的客户端(在系统的不同部分)永远不需要知道Id。所以我应用ISP来提取接口:

public interface User {
    // other methods
}

public interface Room {
    void addUser(User user);
    // other methods
}

并尝试使用ManagedUser和ManagedRoom实现它们。然后发生了一件令人不快的事情:

public class ManagedRoom implements Room {
    @Override
    public void addUser(User user) {
        int userId = user.getId();  // Oops! Cannot get id here.
    }
    // other methods
}

所以我想知道这里的设计是什么。而且,我是否正确理解了ISP?

4 个答案:

答案 0 :(得分:2)

也许您可以定义另一个界面,例如Entity,如下:

public interface Entity {
    int getId();
    void setId(int id);
}

public interface User extends Entity {
    ...
}

public interface Room extends Entity {
    ...
}

答案 1 :(得分:0)

接受

ISP声明:

Clients should not be forced to depend on methods that they do not use.
ISP涉及重要特征 - 内聚和耦合。 理想情况下,您的组件必须高度定制。它提高了代码的健壮性和可维护性。

执行ISP会为您提供以下奖励:

High cohesion - better understandability, robustness
Low coupling - better maintainability, high resistance to changes

并且,您可以在http://www.oodesign.com/interface-segregation-principle.html

学习样本ISP

答案 2 :(得分:0)

我们假设为了完成进入特定房间,只需要用户ID。这至少是您在示例中传递给用户的唯一消息。 我建议要求用户而不是用户:

interface Room {
    public void enter(String userID);
}

现在为了让具体的用户进入一个房间你会有一些东西:

class ManagedUser implements User {

    public void enterRoom(Room room) {
        //provide an ID of some sort to the room
        //particular to ManagedUser world
        room.enter(myID);
    }
}

当然,您可以拥有一个抽象对象用户,允许进入抽象房等。请注意,具体房间可能更新数据库的事实与此级别无关。

class ManagedRoom implements Room {

    public void enter(String userID) {
         //store userID entering this room in whichever way you see fit
    }

}

所以最后进入一个房间会是这样的:

class EnterRoomsGame {

    public void play(User user, Room room) {
        user.enterRoom(room);
    }

}

答案 3 :(得分:0)

在不知道您的用例的情况下很难提出建议。但也许你

我的意思是,提供特定领域的方法(具有"商业意义")并且这个问题可能解决了。

例如,如果这是一个MMORPG,你就可以逃脱:

addUser()

因此,Roompublic interface User { void leaveNorth(); void leaveSouth(); void leaveEast(); void leaveWest(); } 不一定需要相互引用,至少不在界面中。

作为第二种方法,系统的不同部分不一定需要相同的概念"一个UserRoom。这就是埃里克·埃文斯称之为“有限上下文”的内容。来自Martin Fowler的Here is an article关于它。