处理对象字段访问控制的设计模式或方法
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.
- 制作 class "access key".
- 使用 "game hoster" class 将 "key" 实例分配给不同的玩家。
- 棋盘class实例有一个键-右图table。
- 每次玩家对 "read" 或 "move" 动作
板,它必须将它们的关键实例作为方法的参数,
如果权限被拒绝,则抛出异常。
2.use 中间控制器 class
- 棋盘里面有内class"boardcontroller"
- 2子class boardcontroller,1可以移动白棋,另一个可以移动黑棋。
(虽然我可以在这个子 class 中使用一些 if-else 来决定它是否可以移动一些国际象棋,但我想让玩家 class其他程序员写的,让他们写自己的AI,所以这些子class使用的权限判断流程不能直接用在播放器class作为我的问题的方法。)
- 将子板控制器实例分配给不同的玩家。
3.low水平接近(丑陋且不理想)
在板class的"move"或"read"方法中,检查线程的调用堆栈,知道调用者属于class"player",以及它是哪一面(黑色或白色)。
//========================================= ========================
有更好的主意吗?谢谢
无论您如何设置它,您都可以选择通过反射或本机代码传递它。
唯一安全的方法是让组件 运行 在它们自己的进程中,这样它们就无法直接访问彼此。它们可以 运行 作为服务,过滤访问它们的人并限制可以执行的操作。即使这样也不是完全安全的。
但是,如果您通过方法调用使用访问密钥,您就假定了一定程度的信任。如果您愿意承担一定程度的信任,那么也许您可以考虑一个更简单的模型。即我不确定访问密钥的信任级别是正确的安全性。
代理就是你所需要的。
这种设计模式是控制对特定对象的访问,可以控制它们的创建或任何东西。
最好的部分是客户不知道他正在使用代理。
唯一的部分是,如果客户端调用它无法访问的方法,您可以抛出一些异常。在这种情况下,您必须为每个此类方法修改 class 接口以抛出异常,实际实现不会这样做,但为了代理,这是一个很好的解决方案。
a design pattern or approach to handle access control of the fields of an object
每个类型都通过 private
、protected
、public
或包指定对字段和方法的访问控制。如果另一个 class 可以访问另一个对象 - 引用,则它只能调用方法或获取字段值。因此,您必须控制谁可以获得某个对象的引用。
即使代理通常是控制访问的解决方案,您也可以通过设计明确访问权限规则。
对于国际象棋游戏,我会首先设计一个名为ChessPiece
的界面。因为每个玩家都可以看到所有的棋子,所以我会指定一个方法来 returns 棋子的位置。
public interface ChessPiece {
public Position getPosition();
}
所有棋子都放在一个棋盘上。所以下一步是设计一个棋盘,可以访问所有 ChessPiece
s.
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!!!
}
}
众所周知,在许多面向对象的程序语言中,我们可以使用一些访问修饰符来指定对象内部字段的访问范围。
例如,在java中我们可以使用public,protected或private来指定一个字段的访问范围,对于这个对象的所有调用者。
但我的问题是,我想为不同的呼叫者指定被呼叫者的不同访问权限。
最重要的一点是:调用者class可以由其他程序员编写,但在我的主程序编写后,他们无法通过自己的实现更改权限。
例如,假设象棋游戏程序中至少有3个实体,1个棋盘和2个玩家,我想让黑方玩家对棋盘上的所有棋子都有"read"访问权,但只有 "move" 访问所有黑棋的访问权,(并且只有轮到他时才拥有 "move" 权),反之亦然。
我已经有了下面的一些想法,但是这些想法似乎太复杂了,不太理想。
那么有什么好的方法、设计模式或其他方法可以解决这个问题吗?
非常感谢
//========================================= ====================
我的想法:
1.use 访问密钥 class.
- 制作 class "access key".
- 使用 "game hoster" class 将 "key" 实例分配给不同的玩家。
- 棋盘class实例有一个键-右图table。
- 每次玩家对 "read" 或 "move" 动作 板,它必须将它们的关键实例作为方法的参数, 如果权限被拒绝,则抛出异常。
2.use 中间控制器 class
- 棋盘里面有内class"boardcontroller"
- 2子class boardcontroller,1可以移动白棋,另一个可以移动黑棋。
(虽然我可以在这个子 class 中使用一些 if-else 来决定它是否可以移动一些国际象棋,但我想让玩家 class其他程序员写的,让他们写自己的AI,所以这些子class使用的权限判断流程不能直接用在播放器class作为我的问题的方法。)
- 将子板控制器实例分配给不同的玩家。
3.low水平接近(丑陋且不理想)
在板class的"move"或"read"方法中,检查线程的调用堆栈,知道调用者属于class"player",以及它是哪一面(黑色或白色)。
//========================================= ========================
有更好的主意吗?谢谢
无论您如何设置它,您都可以选择通过反射或本机代码传递它。
唯一安全的方法是让组件 运行 在它们自己的进程中,这样它们就无法直接访问彼此。它们可以 运行 作为服务,过滤访问它们的人并限制可以执行的操作。即使这样也不是完全安全的。
但是,如果您通过方法调用使用访问密钥,您就假定了一定程度的信任。如果您愿意承担一定程度的信任,那么也许您可以考虑一个更简单的模型。即我不确定访问密钥的信任级别是正确的安全性。
代理就是你所需要的。
这种设计模式是控制对特定对象的访问,可以控制它们的创建或任何东西。
最好的部分是客户不知道他正在使用代理。 唯一的部分是,如果客户端调用它无法访问的方法,您可以抛出一些异常。在这种情况下,您必须为每个此类方法修改 class 接口以抛出异常,实际实现不会这样做,但为了代理,这是一个很好的解决方案。
a design pattern or approach to handle access control of the fields of an object
每个类型都通过 private
、protected
、public
或包指定对字段和方法的访问控制。如果另一个 class 可以访问另一个对象 - 引用,则它只能调用方法或获取字段值。因此,您必须控制谁可以获得某个对象的引用。
即使代理通常是控制访问的解决方案,您也可以通过设计明确访问权限规则。
对于国际象棋游戏,我会首先设计一个名为ChessPiece
的界面。因为每个玩家都可以看到所有的棋子,所以我会指定一个方法来 returns 棋子的位置。
public interface ChessPiece {
public Position getPosition();
}
所有棋子都放在一个棋盘上。所以下一步是设计一个棋盘,可以访问所有 ChessPiece
s.
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!!!
}
}