最近,我一直在努力解决一些反复出现的设计问题,我不知道如何优雅地解决这些问题。
假设我正在与几个玩家一起制作一款游戏,并为每个玩家制作一些相连的部分。这些部分一起形成一个半复杂的集合或结构。现在我可以通过两种方式实现这个结构:要么通过片段本身的指针隐式存储结构,即:
class BigPiece extends Piece {
Piece opposingPiece, nextPiece, previousPiece, index;
}
或者我可以在集合类中实现这个结构并保持信息集中:
class SomeCollection<Collection<Piece>> {
SomeOtherCollection<Collection<Piece>> collection
= new SomeOtherCollection<Collection<Piece>>();
public SomeCollection() {
collection.add(new PieceCollection<Piece>();
collection.add(new PieceCollection<Piece>();
collection.add(new PieceCollection<Piece>();
}
public Piece getPiece(int playerIndex, int pieceIndex) {
collection.get(playerIndex).get(pieceIndex);
}
public Piece getOpposingPiece(int playerIndex, int pieceIndex) {
int nextPlayerIndex = collection.listIterator(playerIndex).nextIndex();
return this.collection.get(nextPlayerIndex).get(pieceIndex);
}
}
现在我通常喜欢第二种,但这只是根据我的直觉,我在类设计方面没有太多经验,尤其是在大型应用程序方面。我可以看到双方的优点和缺点。
我对第一个解决方案通常遇到的问题是,您仍然必须在某些构建器或工厂中创建实际将对象链接在一起的关联。这对我来说似乎不太稳健。谁能让我放心,在应用程序的整个生命周期中,所有指针实际上都是正确的?
第二种解决方案更加集中数据。但这确实让较高等级的人变得愚蠢(例如个别棋子)。我通常遇到的问题是,每当我想遍历这个集合时,我都必须在较低的级别上进行。你不能问一个棋子“嘿,你的对手是什么?”。不,您必须获得一个游戏对象才能获得指向您的收藏的指针,然后您询问对手的棋子是什么。这使得更多的“管理”类从您的应用程序周围收集数据(方法链接 =( )以最终实现您的算法。这似乎违反了 德墨忒尔法则。
当然,我也可以添加一个指向每个单独作品中相应集合的指针,但我不知道这是否是一个好主意,因为这似乎只是复制 信息。
Lately I've been struggling with some recurrent design problem which I don't know how to solve elegantly.
Say I am making a game with a couple of players and for each player some connected pieces. Together these pieces form a semi-complex collection or structure. Now I could implement this structure in 2 ways: Either store the structure implicitly through pointers in the pieces themselves i.e:
class BigPiece extends Piece {
Piece opposingPiece, nextPiece, previousPiece, index;
}
Or I could implement this structure in a collection class and keep the information centralized:
class SomeCollection<Collection<Piece>> {
SomeOtherCollection<Collection<Piece>> collection
= new SomeOtherCollection<Collection<Piece>>();
public SomeCollection() {
collection.add(new PieceCollection<Piece>();
collection.add(new PieceCollection<Piece>();
collection.add(new PieceCollection<Piece>();
}
public Piece getPiece(int playerIndex, int pieceIndex) {
collection.get(playerIndex).get(pieceIndex);
}
public Piece getOpposingPiece(int playerIndex, int pieceIndex) {
int nextPlayerIndex = collection.listIterator(playerIndex).nextIndex();
return this.collection.get(nextPlayerIndex).get(pieceIndex);
}
}
Now I usually favor the second one, but that's just based on my guts and I don't have that much experience in class design, especially not with big applications. I can see pros and cons on both sides.
The problem I usually have with the first solution is that you still have to create the associations in some builder or factory which actually links the objects together. This doesn't seem very robust to me. Who can reassure me all the pointers are actually correct throughout the application's lifetime?
The second solution centralizes the data more. This really dumbs down the higher classes though (such as individual Pieces). The problem I usually have with this is that whenever I want to traverse this collection, I have to do it on some lower level. You can't ask a piece 'Hey, what's your opposing piece?'. No, you'd have to get a game object to get a pointer to your collection which you then ask what the opposing piece is. This makes more 'managery' classes which collect data from all around your application (method chaining =( ) to finally implement your algorithm. This seems to violate the Law of Demeter.
Sure I could add a pointer to the corresponding collection from each individual piece as well, but I don't know if that's such a good idea since this only seems to be duplicate information.
发布评论
评论(1)
我个人的建议是第二种选择,而不是第一种。正如您所指出的,一件作品不应该(至少在这种情况下)知道它的对立/下一个/上一个作品是什么。
管理器类将更具逻辑意义,可以更好地促进类之间的通信,而不是引用其他块的块。我承认我并不完全了解德米特定律,但维基百科让我相信它是所有关于封装的管理器类实际上也会有帮助!
我不认为棋子(再次,在这种情况下)应该能够移动另一枚棋子。然而,从逻辑上讲,经理阶层会想要这样做。
这就是我的建议,希望对你有帮助!
My personal recommendation is moreso the second option as opposed to the first. As you pointed out, a piece shouldn't (at least in this context) know what its opposing/next/previous piece is.
A manager class would make more logical sense to better facilitate communication between the classes instead of pieces having references to other pieces. I admit I don't fully know about the Law of Demeter but Wikipedia leads me to believe it is all about encapsulation which the manager classes would actually help as well!
I don't think Pieces (again, in this context) should be able to, say, move another piece. However a manager class would logically want to.
That is my suggestion, I hope it helps!