Java 处理对象字段访问控制的设计模式或方法

Java 处理对象字段访问控制的设计模式或方法,java,design-patterns,acl,access-rights,Java,Design Patterns,Acl,Access Rights,我们知道,在许多OO程序语言中,我们可以使用一些访问修饰符来指定对象内字段的访问范围 例如,在java中,我们可以使用public、protected或private为该对象的所有调用方指定字段的访问范围 但我的问题是,我想为不同的呼叫者指定不同的被呼叫者访问权限。 最重要的一点是:调用方类可以由其他程序员编写,但在我的主程序编写完成后,他们不能通过自己的实现更改权限。 例如,假设国际象棋游戏程序中至少有3个实体,1个棋盘和2个玩家,我想让黑方玩家拥有对棋盘上所有国际象棋的“读取”访问权,但只拥

我们知道,在许多OO程序语言中,我们可以使用一些访问修饰符来指定对象内字段的访问范围

例如,在java中,我们可以使用public、protected或private为该对象的所有调用方指定字段的访问范围

但我的问题是,我想为不同的呼叫者指定不同的被呼叫者访问权限。

最重要的一点是:调用方类可以由其他程序员编写,但在我的主程序编写完成后,他们不能通过自己的实现更改权限。

例如,假设国际象棋游戏程序中至少有3个实体,1个棋盘和2个玩家,我想让黑方玩家拥有对棋盘上所有国际象棋的“读取”访问权,但只拥有对所有国际象棋的“移动”访问权(轮到他时只有“移动”权),反之亦然

我已经有一些想法如下,但似乎这些想法太复杂,不理想

那么,有没有什么好的方法、设计模式或其他方法来处理这个问题呢

非常感谢

//===============================================================

我的想法是:

1.使用访问密钥类。

  • 制作一个类“访问密钥”
  • 使用“game hoster”类将“key”实例分配给不同的玩家
  • 棋盘类实例有一个键右映射表
  • 每次玩家朝着目标做“读取”或“移动”动作时 它必须将其关键实例作为方法的参数, 如果权限被拒绝,将引发异常
2.使用中间控制器类

  • 棋盘中有一个内部类“boardcontroller”
  • boardcontroller的2个子类,一个可以移动白棋,另一个可以移动黑棋
(虽然我可以在这个子类中使用一些if-else来决定它是否可以移动一些国际象棋,但我希望让其他编程人员编写玩家类,并让他们编写他们的AI,因此这些子类使用的权限判断流不能直接在玩家类中用作解决我问题的方法。)

  • 将sub boardcontroller实例分配给不同的玩家
3.低级方法(丑陋且不理想)

在board类的“move”或“read”方法中,检查线程的调用堆栈,以了解调用方是否属于类“player”,以及它属于哪一侧(黑色或白色)

//===================================================================


还有更好的主意吗?谢谢

无论您如何设置,您都可以选择通过反射或本机代码传递它

唯一安全的方法是让组件在自己的进程中运行,这样它们就不能直接访问彼此。它们可以作为服务运行,过滤访问它们的用户并限制可以执行的操作。即使这样也不是完全安全的


但是,如果您通过方法调用使用访问密钥,则您将假定一个信任级别。如果你愿意承担一个信任级别,那么也许你可以考虑一个更简单的模型。i、 e.我不确定访问密钥的信任级别是否是适当的安全级别。

代理是您需要的

此设计模式控制对特定对象的访问,可以控制其创建或任何操作

最棒的是,客户不知道他正在使用代理。 唯一的一部分是,若客户机调用它无权访问的方法,您可以抛出一些异常。在这种情况下,您必须为每个此类方法修改类接口以引发异常,实际实现不会这样做,但为了代理,这是一个很好的解决方案

处理对象字段访问控制的设计模式或方法

每种类型都指定仅通过
private
protected
public
或包对字段和方法进行访问控制。另一个类只有在访问另一个对象(引用)时才能调用方法或获取字段值。因此,您必须控制谁可以获得某个对象的引用

即使代理通常是控制访问的解决方案,您也可以通过设计明确访问权限规则

对于国际象棋游戏,我将首先设计一个名为
ChessPiece
的界面。因为每个玩家都能看到所有棋子,我会指定一个方法返回棋子的位置

public interface ChessPiece {
    public Position getPosition();
}
public class Player {

    private Collection<PlayersChessPiece> ownPieces;
    private Chessboard chessboard;

    public Player(Chessboard chessboard, Collection<PlayersChessPiece> ownPieces){
        this.chessboard = chessboard;
        this.ownPieces = ownPieces;
    }
}
所有棋子都放在棋盘上。因此,下一步是设计一个棋盘,允许访问所有
棋子

public interface Chessboard {
    public Collection<ChessPiece> getChessPieces();
}
因为一个玩家只能移动他自己的棋子,我把这方面的设计

public interface PlayersChessPiece extends ChessPiece {
    public void move(Position position) throws MoveNotSupported;
}
这个设计背后的想法很简单。方法属于一个类,而对象是某个类的实例。只有当有权访问对象(引用)时,才能调用方法。因此,访问权限可以简单地表示为将访问权限透视图放在其他对象上的对象。您只需确保为客户提供了正确的参考


当然,有人可以使用反射攻击对象并访问私有字段。您只能通过安装一个

这种访问控制设计模式可能是一种解决方案:

这是本文中使用模式的示例:

// ******** VirtualMethod ********
public abstract class VirtualMethod {
    public abstract void call();
}
// ******** Server ********
public class Server {

    private void shakeRattleAndRoll() {
        System.out.println("SHAKE ... RATTLE AN' ROLL!!!");
    }
    private class ShakeRattleAndRoll extends VirtualMethod {
        public void call() {
             shakeRattleAndRoll();
        }
    }
    public Client getClient() {
        return new Client(new ShakeRattleAndRoll());
    }

}
// ******** Client ********
public class Client {

    private VirtualMethod shakeRattleAndRoll;

    public Client(VirtualMethod shakeRattleAndRoll) {
        this.shakeRattleAndRoll = shakeRattleAndRoll;
    }

    public void demonstrateAccess() {
        shakeRattleAndRoll.call();
    }

}
// ******** Test ********
public class Test {
    public static void main(String[] args) {
        Server server = new Server();
        Client client = server.getClient();
        client.demonstrateAccess();           // Prints out:  SHAKE ... RATTLE AN' ROLL!!!
    }
}

没有必要是一些“设计模式”的东西,只是一个好的方法或技巧就可以了。考虑过使用代理吗?是的,我曾想过将棋盘作为一个服务过程来编写,让玩家使用restful或与棋盘相关的东西来玩。但这似乎还是太复杂了。我同意,可能是这样,如果你有足够的决心,有办法解决这个问题