How to create two interfaces to a Java class one read

I'm writing a game engine in Java for a two player card game for which my students are going to write AI players.

The AI players will take turns playing cards onto their 'field' a part of the 'table' in front of them. They can attack with a card from their field a card in the other player's field. Cards may be face up or face down.

The GameEngine class allows an AI player to take his/her turn by calling the GamePlayer.TakeTurn(GameEngine eng) method. The player can ask the game engine for the defending player's field so the player can make decisions based on the number of cards there and which ones are face up. Let's say this method is GameEngine.GetDefendingField()

Now, I want to make sure that the attacking player cannot modify the defending player's field or the cards in the defending player's field and that the attacking player can only identify the face up cards in the defending players field.

I have classes for Card, Field (an ArrayList of Cards), GamePlayer and GameEngine. Is there any way to create an interface for Field so that the GameEngine can return the defending player's field without the attacking player being able to change it? and without the attacking player being able to recast the defending player's field into something that can be changed.

Can I have GameEngine.GetDefendingField() return a read-only interface to a Field that cannot be recast to a Field?

tia,

Sh-


If you want to achieve this without copying and without the possibility to cast the read-only interface reference to a corresponding read-write interface, you could try to use a wrapper approach.

For an interface like this:

interface Info {
    String getInfoA();
    void setInfoA(String infoA);
    String getInfoB();
    void setInfoB(String infoB);
}

You could create a readonly wrapper which ignores the setters or throws exceptions, like:

class ReadonlyInfo implements Info {
    final Info instance;
    ReadonlyInfo(Info info) { 
         if (null == info) { throw new InvalidArgumentException(); } 
         instance = info; 
    }
    String getInfoA() { return instance.getInfoA(); }
    void setInfoA(String infoA) { /** silent ignore */ }
    String getInfoB() { return instance.getInfoB(); }
    void setInfoB(String infoA) { throw new IllegalStateException(); }
}

By using the wrapper approach you can use polymorphism on the client side, be safe against casting the reference to get more access rights and chose between silently ignore called setters, or throwing an illegal access exception.

Note: of course you will not be safe against code that uses reflection to retrieve the wrapped object.


You're talking basic Model-View-Controller here, with your Model being Card and Field, the Controller is GamePlayer and GameEngine, and the View is as-of-yet undefined. Your Field is your Model, and you would want to create 2 different interfaces that would access the Field model, one read-only and one read-write. Your read-write implementation would likely just return the Field object. Your read-only implementation would rip thru the elements in the Field and only return the ones that they have access to, doing a deep copy of each Card in the Field returned.


I like the idea of using type safety and polymorphism to control this sort of access control at compile time, especially when teaching.

A good way to approach it would be to have two Field interfaces. Maybe Field and MutableField, where the latter extends the former and adds the change methods. Your FieldImpl could of course implement both.

The problem, of course, is that you want to return different declared types (Field or MutableField) from your game engine based on whose field you are using. If you have a single model, you could use something like getMyField() and getOtherPlayerField() since it appears from the description that when making a call to getField() one knows exactly which field it is that they want.

链接地址: http://www.djcxy.com/p/50208.html

上一篇: 如何创建自定义javadoc标签?

下一篇: 如何为一个读取的Java类创建两个接口