Compare commits
2 Commits
3aac90b9a7
...
9a696c8211
Author | SHA1 | Date |
---|---|---|
Fred Pauchet | 9a696c8211 | |
Fred Pauchet | 0d9d90cd3d |
|
@ -0,0 +1,58 @@
|
|||
<mxfile host="Electron" modified="2024-03-26T08:10:45.260Z" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/22.0.3 Chrome/114.0.5735.289 Electron/25.8.4 Safari/537.36" etag="ChN9pPi8goOMF3hpUA-N" version="22.0.3" type="device">
|
||||
<diagram name="Page-1" id="hcI3l78rCcP6oUjfjhzO">
|
||||
<mxGraphModel dx="954" dy="598" grid="0" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="0" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
<mxCell id="8Q815A0daQfj0QbWb1XH-12" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="8Q815A0daQfj0QbWb1XH-1" target="8Q815A0daQfj0QbWb1XH-9" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="8Q815A0daQfj0QbWb1XH-1" value="Character" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="200" y="120" width="120" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="8Q815A0daQfj0QbWb1XH-6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="1" source="8Q815A0daQfj0QbWb1XH-2" target="8Q815A0daQfj0QbWb1XH-1" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="8Q815A0daQfj0QbWb1XH-2" value="Queen" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="30" y="230" width="120" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="8Q815A0daQfj0QbWb1XH-5" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="8Q815A0daQfj0QbWb1XH-3" target="8Q815A0daQfj0QbWb1XH-1" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="8Q815A0daQfj0QbWb1XH-3" value="King" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="200" y="230" width="120" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="8Q815A0daQfj0QbWb1XH-7" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="1" source="8Q815A0daQfj0QbWb1XH-4" target="8Q815A0daQfj0QbWb1XH-1" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="8Q815A0daQfj0QbWb1XH-4" value="..." style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="370" y="230" width="120" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="8Q815A0daQfj0QbWb1XH-8" value="is-a" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="250" y="180" width="60" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="8Q815A0daQfj0QbWb1XH-9" value="Weapon Behaviour" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="550" y="120" width="120" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="8Q815A0daQfj0QbWb1XH-11" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="8Q815A0daQfj0QbWb1XH-10" target="8Q815A0daQfj0QbWb1XH-9" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="8Q815A0daQfj0QbWb1XH-10" value="Knife Behaviour" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="550" y="230" width="120" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="8Q815A0daQfj0QbWb1XH-13" value="as-a" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="420" y="120" width="60" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="8Q815A0daQfj0QbWb1XH-15" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="1" source="8Q815A0daQfj0QbWb1XH-14" target="8Q815A0daQfj0QbWb1XH-9" edge="1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="8Q815A0daQfj0QbWb1XH-14" value="..." style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="730" y="230" width="120" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="8Q815A0daQfj0QbWb1XH-16" value="is-a" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
|
||||
<mxGeometry x="600" y="180" width="60" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
Binary file not shown.
After Width: | Height: | Size: 74 KiB |
|
@ -26,21 +26,110 @@ Pour rappel, la Programmation Orientée Objets se base sur les principes suivant
|
|||
|
||||
### Factory & Abstract Factory
|
||||
|
||||
|
||||
### Singleton
|
||||
|
||||
|
||||
## Behavioral
|
||||
|
||||
|
||||
### Command
|
||||
|
||||
|
||||
### Iterator
|
||||
|
||||
|
||||
### Template
|
||||
|
||||
Celui-ci, c'est un peu mon chouchou.
|
||||
Il consiste à définir les grandes étapes du comportement d'un modèle, pouvant être réutilisé entre plusieurs autres définitions.
|
||||
|
||||
Ainsi, les deux classes ci-dessous présentent les mêmes étapes d'un algorithme - elles sont juste nommées différemment :
|
||||
|
||||
```python
|
||||
class Coffee:
|
||||
def boil_water(self):
|
||||
...
|
||||
|
||||
def brew_coffee_grinds(self):
|
||||
...
|
||||
|
||||
def pour_in_cup(self):
|
||||
...
|
||||
|
||||
def add_sugar_and_milk(self):
|
||||
...
|
||||
|
||||
|
||||
class Tea:
|
||||
def boil_water(self):
|
||||
...
|
||||
|
||||
def steep_tea_bag(self):
|
||||
...
|
||||
|
||||
def pour_in_cup(self):
|
||||
...
|
||||
|
||||
def add_lemon(self):
|
||||
...
|
||||
```
|
||||
|
||||
On peut voir que la finalité est la même ("_servir une boisson chaude_"), tandis que les étapes varient légèrement, mais restent fortement similaires, et consistent à :
|
||||
|
||||
1. Faire bouillir de l'eau,
|
||||
2. Préparer l'infusion,
|
||||
3. Servir dans une tasse,
|
||||
4. Ajouter des condiments.
|
||||
|
||||
Ces quatre étapes constituent les quatre méthodes principales d'une classe `CaffeineBeverage`, que l'on peut traduire de la manière suivante :
|
||||
|
||||
```python
|
||||
class CaffeineBeverage:
|
||||
def boil_water(self):
|
||||
...
|
||||
|
||||
def brew(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
def pour_in_cup(self):
|
||||
...
|
||||
|
||||
def add_condiments(self):
|
||||
...
|
||||
```
|
||||
|
||||
Nous pouvons à présent modéliser nos deux (sous-)classes `Coffee` & `Tea` simplement en surchargeant les méthodes qui nous intéressent, et en laissant le template faire le reste de son travail :
|
||||
|
||||
```python
|
||||
class Coffee(CaffeineBeverage):
|
||||
[snip]
|
||||
|
||||
def brew(self):
|
||||
self.brew_coffee_grinds()
|
||||
|
||||
|
||||
class Tea(CaffeineBeverage)
|
||||
[snip]
|
||||
|
||||
def brew(self):
|
||||
self.steep_tea_bag()
|
||||
```
|
||||
|
||||
![](template.png)
|
||||
|
||||
Le _template_ définit donc le squelette d'un algorithme dans une méthode, en autorisant aux sous-classes de surcharger certaines parties de cet algorithme, sans en changer la nature intrinsèque.
|
||||
Il est tout aussi facile de définir des _hooks_, qui permettent à la sous-classe de définir un comportement sur base de _flags_.
|
||||
|
||||
Les tableaux utilisent ce pattern pour les tris en utilisant les méthodes `.CompareTo()` (ou équivalentes) ou la surcharge d'opérateurs (`__lte__`, `__gte__`, ...).
|
||||
|
||||
### State
|
||||
|
||||
|
||||
|
||||
### Observer
|
||||
|
||||
|
||||
### Strategy
|
||||
|
||||
> Plutôt que d'implémenter une forme d'héritage dès qu'on en a l'occasion, l'idée est de différencier l'élément de son comportement.
|
||||
|
@ -55,7 +144,7 @@ De cette manière, il suffit de déclarer une nouvelle classe, puis de lui injec
|
|||
Une autre conclusion est qu'il est parfois mieux d'implémenter un `has-a` (= composition, délégation, ...) qu'un `is-a` (= héritage).
|
||||
De la même manière, nous pouvons implémenter des personnes d'un jeu de rôles et "réutiliser" leurs armes en définissant un `WeaponBehaviour` :
|
||||
|
||||
![](strategy.drawio.png)
|
||||
![](strategy.png)
|
||||
|
||||
[^1]: en mode, "_Si vous faites de l'héritage sans réfléchir, vous allez vous planter_".
|
||||
|
||||
|
@ -63,12 +152,25 @@ De la même manière, nous pouvons implémenter des personnes d'un jeu de rôles
|
|||
|
||||
### Composite
|
||||
|
||||
L'intérêt des composite est de représenter des éléments contenant d'autres éléments d'un même type.
|
||||
Le modèle analysé se base sur des "menus" (d'un restaurant), qui peuvent contenir d'autres sous-menus.
|
||||
Il s'agit donc d'un _pattern_ pouvant servir à représenter des arborescences - où nous trouverons des noeuds et des feuilles d'un arbre.
|
||||
|
||||
![](composite.png)
|
||||
|
||||
Attention qu'en termes de performances, ce pattern doit généralement être couplé à d'autres mécanismes (caching, dénormalisation, [MPTT](https://stackabuse.com/modified-preorder-tree-traversal-in-django/), ...).
|
||||
|
||||
|
||||
### Decorator
|
||||
|
||||
|
||||
### Adapter
|
||||
|
||||
|
||||
### Façade
|
||||
|
||||
|
||||
### Proxy
|
||||
|
||||
|
||||
### Compound
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 21 KiB |
Binary file not shown.
After Width: | Height: | Size: 48 KiB |
Binary file not shown.
After Width: | Height: | Size: 58 KiB |
Loading…
Reference in New Issue