What is a design pattern to enable a class (Block
) to be viewed from different perspectives (Orientation
)?
Example
I have a 3D block. It stores values at its 6 faces.
class Block{
public: int faces[6];
public: enum Direction{
X_POSITIVE, X_NEGATIVE,
Y_POSITIVE, Y_NEGATIVE,
Z_POSITIVE, Z_NEGATIVE
}
public: int& getFace(Direction dir){
return faces[dir];
}
};
If I use Block's axis, I can assign a value of face easily:-
Block block;
block.getFace(Block::Direction::X_POSITIVE)=5;
However, in some part of program, I prefer to view Block from a certain orientation :-
//I want to rotate the block by "transform" then view as usual
Transform transform=Transform::create_rotateByX90Degree();
block.getFace(transform,Block::X_POSITIVE)=5;
As I have to query getFace()
many times in rows, I have to pass transform
every time.
This becomes messy:-
int& a = block.getFace(transform,Block::X_POSITIVE);//<-- "transform"
int& b = block.getFace(transform,Block::Y_POSITIVE);//<-- "transform" again (#)
Question
What is a design pattern to solve this repetitive code(#)?
My poor solution
I would create a Viewer
.
Transform transform=Transform::create_rotateByX90Degree();
Viewer viewer = Block::createViewer(block,transform);
viewer.getFace(Block::X_POSITIVE);
viewer.getFace(Block::Y_POSITIVE);
It looks good, but has two certain maintainability problems :-
Every field must be encapsulated
If Block
has many fields e.g. int faces2[6]
, I will have to create additional functions in Viewer
e.g. Viewer::getFace2()
.
More repetitive code for fields that also want Viewer
Furthermore, if Block
has a more complex field, and the field's viewed value
depend on transform
again, I have to encapsulate the field too.
class Block{
Member members[6];
}
Transform transform=Transform::create_rotateByX90Degree();
Viewer viewer = Block::createViewer(block,transform);
Member & member = viewer.getMember(Block::X_POSITIVE);
//Here, I get "member" that is inside "block",
// but I have to encapsulate "member" by another viewer again.
ViewerMember viewerD = ViewerMember::createViewerD(member ,transform);
ViewerMember.getSomething();
Aucun commentaire:
Enregistrer un commentaire