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

a design pattern or approach to handle access control of the fields of an object

众所周知,在许多面向对象的程序语言中,我们可以使用一些访问修饰符来指定对象内部字段的访问范围。

例如,在java中我们可以使用public,protected或private来指定一个字段的访问范围,对于这个对象的所有调用者。

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

最重要的一点是:调用者class可以由其他程序员编写,但在我的主程序编写后,他们无法通过自己的实现更改权限。

例如,假设象棋游戏程序中至少有3个实体,1个棋盘和2个玩家,我想让黑方玩家对棋盘上的所有棋子都有"read"访问权,但只有 "move" 访问所有黑棋的访问权,(并且只有轮到他时才拥有 "move" 权),反之亦然。

我已经有了下面的一些想法,但是这些想法似乎太复杂了,不太理想。

那么有什么好的方法、设计模式或其他方法可以解决这个问题吗?

非常感谢

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

我的想法:

1.use 访问密钥 class.

2.use 中间控制器 class

(虽然我可以在这个子 class 中使用一些 if-else 来决定它是否可以移动一些国际象棋,但我想让玩家 class其他程序员写的,让他们写自己的AI,所以这些子class使用的权限判断流程不能直接用在播放器class作为我的问题的方法。)

3.low水平接近(丑陋且不理想)

在板class的"move"或"read"方法中,检查线程的调用堆栈,知道调用者属于class"player",以及它是哪一面(黑色或白色)。

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

有更好的主意吗?谢谢

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

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

但是,如果您通过方法调用使用访问密钥,您就假定了一定程度的信任。如果您愿意承担一定程度的信任,那么也许您可以考虑一个更简单的模型。即我不确定访问密钥的信任级别是正确的安全性。

代理就是你所需要的。

这种设计模式是控制对特定对象的访问,可以控制它们的创建或任何东西。

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

Reference

a design pattern or approach to handle access control of the fields of an object

每个类型都通过 privateprotectedpublic 或包指定对字段和方法的访问控制。如果另一个 class 可以访问另一个对象 - 引用,则它只能调用方法或获取字段值。因此,您必须控制谁可以获得某个对象的引用。

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

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

public interface ChessPiece {
    public Position getPosition();
}

所有棋子都放在一个棋盘上。所以下一步是设计一个棋盘,可以访问所有 ChessPieces.

public interface Chessboard {
    public Collection<ChessPiece> getChessPieces();
}

A Player 可以访问棋盘,因此可以看到所有棋子。但是 Player 只允许移动他自己的棋子。因此 Player 必须获得一种特殊的棋子。

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 PlayersChessPiece extends ChessPiece {
    public void move(Position position) throws MoveNotSupported;
}

这个设计背后的想法很简单。一个方法属于一个class,一个对象是某个class的一个实例。如果某人有权访问对象(引用),则某人只能调用方法。因此,访问权限可以简单地由将访问权限透视到其他对象的对象来表示。您只需确保向客户提供正确的参考资料。

当然有人可以破解对象并使用反射访问私有字段。您只能通过安装 security manager 来防止这种情况。

也许这个访问控制设计模式是一个解决方案:https://www.javaworld.com/article/2075599/java-security/access-control-for-partial-exposure.html

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

// ******** 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!!!
    }
}