Vous êtes sur la page 1sur 36

Module M3105 – Programmation objet avancée

COURS N°4

Principe ouvert/fermé
Le décorateur
La fabrique
PRINCIPE
OUVERT/FERMÉ

Module M3105 – Programmation objet avancée


Open/closed principle
• Une classe doit être
– ouverte à l’extension
– fermée à la modification
• Seules modifications autorisées dans une
classe
– correction des erreurs
– refactoring des membres privés

M3105 Alexandre Guidet


Mise en œuvre du principe
• Difficulté : isoler les méthodes risquant
d’évoluer
• Conseil : ne pas devoir dépendre d’un type
particulier
• Association : utiliser une classe abstraite
• Association entre différentes couches :
utiliser une interface

M3105 Alexandre Guidet


Exemple
Client

Use(s : Server)

Server

doSomething()

Server est concrète


On ne peut pas remplacer Server (sauf
par une héritière)
Impossible d’utiliser un autre serveur…

M3105 Alexandre Guidet


Exemple
Server2

<<Interface>>
Client
IServer
Use(s : IServer)
doSomething()

Server1

IServer est une interface


On peut utiliser n’importe quelle
classe qui implémente cette interface
Evolution facile !

M3105 Alexandre Guidet


Car(MotorType m)
Exemple {
if(m==GAS)
motor=new GasMotor();
else if(m==DIESEL)
• Premier modèle motor = new DieselMotor();
/* … */
• ne respecte pas O }

Car

Car(MotorType m)
start()

<<Énumeration>>
MotorType
Motor
GAS
DIESEL
GPL
ELECTRIC

GasMotor DieselMotor

start() start()

M3105 Alexandre Guidet


Exemple est devenue fermée à
la modification

• Deuxième modèle reste ouverte…

• respecte O ?
Car
<<Énumeration>>
Car(m : MotorType) MotorType
GAS
DIESEL
GPL
ELECTRIC
Motor

MotorFactory

createMotor(t : MotorType) : Motor

GasMotor

DieselMotor

M3105 Alexandre Guidet


Exemple : dernier modèle
CreateGasMotor

<<Interface>>
CreateMotor
Car create() : Motor

+Car(typeMotor : string) *

Motor MotorFactory

createMotor(type:string) : Motor
register(cm : createMotor, type:string)

GasMotor
DieselMotor

M3105 Alexandre Guidet


LA FABRIQUE
ABSTRAITE

Module M3105 – Programmation objet avancée


Généralités
• Besoin
– Construire de manière générique des héritières
d'une classe de base
– Avoir un constructeur "polymorphe"
• Principe
– Créer une interface associée à la classe de base pour
construire une instance
– Chaque classe concrète est fournie avec une
implémentation de cette interface
– La fabrique compose ces implémentations
– Chaque type peut être référencé par une clé

M3105 Alexandre Guidet


Structure statique

constructors *

Factory
<<Interface>>
Mother
Constructor Types() : [*]
Mother() Create(type) : Mother
Create() : Mother

Child1 Child2 Construc1 Construc2

Child1() Child2()

<<instantiate>>

<<instantiate>>

M3105 Alexandre Guidet


Implémentation C#
• Utilisation d'un dictionnaire pour repérer le
"constructeur" par une clé
• Utilisation d'une chaîne pour clé
• Utilisation d'un ensemble pour lister les clés
possibles

M3105 Alexandre Guidet


Implémentation C#
class Factory
{
private Dictionary<string,Constructor>
constructors = new Dictionary<string,
Constructor >();

M3105 Alexandre Guidet


Implémentation C#
public Mother Create(string Type) {
if(!constructors.ContainsKey(Type))
throw new Exception("Type "+Type+"
unknown");

return constructors[Type].create();
}

public string[] Types() {


return constructors.Keys.ToArray();
}

M3105 Alexandre Guidet


Exemple

Human

+Human(name:string)

Animal
Dog <<property> Name :string
Animal(name : string)
Bird
+Dog(name:string)
+Speak() : string
+Speak() : string +Bird(name:string)
+Species() : string
+Species() : string +Speak() : string
+Food() : string
+Food() : string
+ToString() : string
+Race() : string

Cocker Shepherd Eagle Vulture

+Cocker(name:string) +Shepherd(name:string) +Eagle(name:string) +Vulture(name:string)

projet complet sur dossier commun


M3105 Alexandre Guidet
Fabrique (singleton)
class AnimalFactory {
private static AnimalFactory instance = null;
private AnimalFactory() { }
public static AnimalFactory Instance
{
get
{
if (instance == null)
instance = new AnimalFactory();
return instance;
}
}

M3105 Alexandre Guidet


Fabrique (gestion des types)
private Dictionary<String, MakeAnimal>
constructors = new Dictionary<string,
MakeAnimal >();
public void Register(String type, MakeAnimal
cons)
{
constructors[type] = cons;
}
public String[] Types
{
get { return constructors.Keys.ToArray(); }
}

M3105 Alexandre Guidet


Fabrique (création)
public Animal Create(string type, string
name)
{
if (!constructors.ContainsKey(type))
throw new Exception("Type " + type + "
unknown");

return constructors[type].Create(name);
}

M3105 Alexandre Guidet


"Constructeurs virtuels"
interface MakeAnimal
{
Animal Create(string name);
}
class MakeCocker : MakeAnimal
{
public MakeCocker(){
AnimalFactory.Instance.Register("cocker",this);
}
public Animal Create(string name)
{
return new Cocker(name);
}
}

M3105 Alexandre Guidet


Initialisation des types
new MakeEagle();
new MakeShepherd();
new MakeCocker();
new MakeVulture();
new MakeHuman();

Certaines méthodes permettent d’éviter ces lignes de code !

M3105 Alexandre Guidet


Utilisation dans une IHM
• IHM utilisant le framework WPF
• Type dans une boite liste
• Nom dans une zone de saisie
• utilise la fabrique

M3105 Alexandre Guidet


Initialisation de l'IHM
string[] types =
AnimalFactory.Instance.Types;

foreach (String s in types)


species.Items.Add(s);

M3105 Alexandre Guidet


Création d'animal
• Action : clic sur bouton « new »
• Code indépendant du type réel
if(species.SelectedItem is string type)
{
Animal a =
AnimalFactory.Instance.Create(type, name.Text);

animals.Items.Add(a);
}

M3105 Alexandre Guidet


LE DÉCORATEUR

Module M3105 – Programmation objet avancée


Le modèle décorateur
• Besoin
– ajouter dynamiquement des fonctionnalités à un
objet
• Principe
– créer une classe composant la classe à décorer et
implémentant la même interface
– implémenter une classe par décoration souhaitée
– chaînage des décorations

M3105 Alexandre Guidet


Structure statique
<<Interface>>
1
IComponent Component

operation()

Decorator

operation()
Decorator( c : IComponent)

Decorator1 Decorator2
operation() operation()

M3105 Alexandre Guidet


Exemple en C# : les points
• Classe de départ : un point du plan
• Fonctionnalités de départ :
– déplacement du point
– Conversion en chaîne
• Décorations possibles :
– coloration du point
– passage en 3 dimensions

M3105 Alexandre Guidet


Exemple en C# : interface
interface IPoint
{
void Move(int[] dp);
string ToString();
}

M3105 Alexandre Guidet


Exemple en C# : la classe Point
class Point : IPoint {
private int x;
private int y;
public Point( int _x, int _y) {…}
public void Move(int[] dp) {
x += dp[0]; y += dp[1];
}
public string ToString() {
return x.ToString()+";"+y.ToString());
}
}

M3105 Alexandre Guidet


Exemple en C# : décorateur de Point
class PointDecorator : IPoint
{
private IPoint pt;
public PointDecorator
(IPoint p)
{ pt = p;}

M3105 Alexandre Guidet


Exemple en C# : décorateur de Point
public void Move(int[] dp)
{
pt.Move(dp);
}
public string ToString()
{
return pt.ToString();
}

M3105 Alexandre Guidet


Exemple en C# : colorer un point
class ColorPoint :
PointDecorator {
private Color color;
public ColorPoint(IPoint p,
Color c) : base(p)
{
color = c;
}

M3105 Alexandre Guidet


Exemple en C# : colorer un point
public string ToString() {
return base.ToString()
+ " "+color.ToString();
}

M3105 Alexandre Guidet


Exemple en C# : colorer un point
Point p = new Point(10,20);
Console.WriteLine(p);
p = new Point3D(p,30);
Console.WriteLine(p);
p = new ColorPoint(p,Color.RED);
Console.WriteLine(p);

10;20
10;20;30
10;20;30 RED
M3105 Alexandre Guidet
Module M3105 – Programmation objet avancée

PROCHAIN COURS

Principe D
Adaptateur, Observateur

Vous aimerez peut-être aussi