Orienté objet
La programmation orientée objet consiste à demander aux objets de faire quelque chose : un concept faussement difficile à appliquer correctement.
Goban
Considérez un plateau de jeu en 2D, comme pour jouer Allez sur (appelé goban ).
Pensez d'abord au comportement qu'il faut adopter pour accomplir sa tâche. Cela signifie qu'il faut dresser la liste des comportements d'un objet plutôt que de décider des données que les comportements manipulent. Par exemple, un tableau de base pourrait avoir les comportements suivants :
- Placez une pierre de Go.
- Retirer une pierre de Go.
- Enlevez toutes les pierres.
Pour une version informatique du Go, il est pratique d'attirer l'attention sur des zones spécifiques :
- Marquez une intersection (par exemple, triangle, chiffre, lettre, cercle, carré).
- Supprimer une marque d'une intersection marquée.
- Enlevez toutes les marques.
Notez qu'un goban n'a pas besoin de fournir un moyen de fournir aux clients une référence à la pierre à une intersection spécifique. Au lieu de cela, il peut répondre à des questions sur son état. Par exemple, une goban pourrait répondre aux questions suivantes :
- Y a-t-il une pierre noire à une intersection donnée ?
- Y a-t-il une pierre blanche à une intersection donnée ?
- Y a-t-il une marque à une intersection donnée ?
Il n'est pas de la responsabilité de l goban pour connaître l'état du jeu : cela appartient à une instance d'une Jeu (qui a Règles ). Dans la vie réelle, un goban est simplement une scène pour les pierres.
A ce stade, nous pourrions écrire une interface pour une goban sans savoir comment l'implémentation sous-jacente fonctionnera.
public interface Goban {
public void place( Stone stone, Point point );
public void removeStone( Point point );
public void removeStones();
public void place( Mark mark, Point point );
public void removeMark( Point point );
public void removeMarks();
public boolean hasWhiteStone( Point point );
public boolean hasBlackStone( Point point );
public boolean hasMark( Point point );
}
Remarquez comment la planche est proprement séparée des deux Règles y Jeux . Cela rend le goban réutilisable pour d'autres jeux (impliquant des pierres et des intersections). Le site goban pourrait hériter d'une interface générique (par exemple, une Conseil d'administration ), mais cela devrait suffire à expliquer une façon de penser en termes d'objets.
Encapsulation
Une mise en œuvre de la Goban n'expose pas ses données internes. À ce stade, je pourrais vous demander d'implémenter cette interface, d'écrire des tests unitaires et de m'envoyer la classe compilée lorsque vous aurez terminé.
Je n'ai pas besoin de savoir quelles structures de données vous avez utilisées. Je peux utiliser votre implémentation pour jouer sur (et représenter) un Goban. Il s'agit d'un point crucial que de nombreux projets ne maîtrisent pas. Beaucoup, beaucoup de projets codent ce qui suit :
public class Person {
private HairColour hairColour = new HairColour( Colour.BROWN );
public Person() {
}
public HairColour getHairColour() {
return hairColour;
}
public void setHairColour( HairColour hairColour ) {
this.hairColour = hairColour;
}
}
C'est une encapsulation inefficace. Considérons le cas où Bob n'aime pas que ses cheveux soient colorés en rose. Nous pouvons faire ce qui suit :
public class HairTrickster {
public static void main( String args[] ) {
Person bob = new Person();
HairColour hc = bob.getHairColour();
hc.dye( Colour.PINK );
}
}
Bob s'est maintenant fait colorer les cheveux en rose, et rien ne pouvait l'en empêcher. Il existe des moyens d'éviter cette situation, mais les gens ne les appliquent pas. Au lieu de cela, l'encapsulation est rompue, ce qui donne des systèmes rigides, inflexibles, truffés de bogues et impossibles à maintenir.
Une manière possible de renforcer l'encapsulation est de retourner un clone de HairColour
. La classe Personne révisée rend maintenant difficile le changement de la couleur des cheveux en Rose.
public class Person {
private HairColour hairColour = new HairColour( Colour.BROWN );
public Person() {
}
public HairColour getHairColour() {
return hairColour.clone();
}
public void setHairColour( HairColour hairColour ) {
if( !hairColour.equals( Colour.PINK ) {
this.hairColour = hairColour;
}
}
}
Bob peut dormir sur ses deux oreilles, sachant qu'il ne se réveillera pas avec une teinture rose.