diff --git a/src/main/java/fr/univlille/iut/r304/tp3/q1/Observable.java b/src/main/java/fr/univlille/iut/r304/tp3/q1/Observable.java
index 264f8c55116271d3ba3958a89fa337fa381cbdb3..2e0a79c7aa73da5c64423ee1d8337feec225709c 100644
--- a/src/main/java/fr/univlille/iut/r304/tp3/q1/Observable.java
+++ b/src/main/java/fr/univlille/iut/r304/tp3/q1/Observable.java
@@ -1,17 +1,31 @@
 package fr.univlille.iut.r304.tp3.q1;
 
+import java.util.Queue;
+import java.util.Set;
+import java.util.concurrent.ConcurrentLinkedQueue;
 
 public abstract class Observable {
+	protected Queue<Observer> observers = new ConcurrentLinkedQueue<>();
 
 	protected void notifyObservers() {
+		for (Observer observer:observers
+			 ) {
+			observer.update(this);
+		}
 	}
 
 	protected void notifyObservers(Object data) {
+		for (Observer observer:observers
+		) {
+			observer.update(this, data);
+		}
 	}
 
 	public void attach(Observer observer) {
+		observers.add(observer);
 	}
 
 	public void detach(Observer observer) {
+		observers.remove(observer);
 	}
 }
diff --git a/src/main/java/fr/univlille/iut/r304/tp3/q2/Objectif.java b/src/main/java/fr/univlille/iut/r304/tp3/q2/Objectif.java
new file mode 100644
index 0000000000000000000000000000000000000000..09aeaf11f75a77504bebe36b7949f4b69879977b
--- /dev/null
+++ b/src/main/java/fr/univlille/iut/r304/tp3/q2/Objectif.java
@@ -0,0 +1,49 @@
+package fr.univlille.iut.r304.tp3.q2;
+
+import fr.univlille.iut.r304.tp3.q1.Observable;
+import fr.univlille.iut.r304.tp3.q1.Observer;
+
+public class Objectif implements Observer {
+    protected int nbRestant;
+    protected String nom;
+
+    Objectif(String nom, int nbRestant){
+        this.nom = nom;
+        this.nbRestant = nbRestant;
+    }
+    public int getNbRestant(){
+        return this.nbRestant;
+    }
+
+    public String getNom(){
+        return this.nom;
+    }
+
+
+    protected void updateObjectif(Object data){
+        nbRestant --;
+    }
+    @Override
+    public void update(Observable subj) {
+
+    }
+
+    @Override
+    public String toString() {
+        return nom + " - nombre de lignes restantes : encore " + nbRestant;
+    }
+
+    @Override
+    public void update(Observable subj, Object data) {
+        updateObjectif(data);
+        if (!data.equals("!fin")) {
+            if (nbRestant > 0) {
+                System.out.println(this.toString());
+            } else {
+                System.out.println(nom + " - nombre atteint");
+            }
+        }
+
+    }
+
+}
diff --git a/src/main/java/fr/univlille/iut/r304/tp3/q2/ObjectifNbLettre.java b/src/main/java/fr/univlille/iut/r304/tp3/q2/ObjectifNbLettre.java
new file mode 100644
index 0000000000000000000000000000000000000000..268ca5e26949f6ac66d62ebd08ebcd8b530a862c
--- /dev/null
+++ b/src/main/java/fr/univlille/iut/r304/tp3/q2/ObjectifNbLettre.java
@@ -0,0 +1,37 @@
+package fr.univlille.iut.r304.tp3.q2;
+
+public class ObjectifNbLettre extends Objectif{
+    String lettre;
+
+    ObjectifNbLettre(String nom, int nbRestant, String lettre){
+        super(nom, nbRestant);
+        this.lettre = lettre;
+    }
+
+    @Override
+    protected void updateObjectif(Object data){
+        String text = (String) data;
+        int nbLettre = 0;
+        nbLettre = text.length() - text.replaceAll(lettre, "").length();
+        super.nbRestant -= nbLettre;
+    }
+
+    @Override
+    public String toString() {
+        return nom + " - nombre de "+ lettre+" restants : encore " + nbRestant;
+    }
+
+    public static void main(String[] args) {
+        Objectif objectif = new Objectif("Objectif 1", 3);
+        ObjectifNbLettre objectif2 = new ObjectifNbLettre("Objectif 2", 3, "e");
+        Texte texte = new Texte(System.in);
+        texte.attach(objectif);
+        texte.attach(objectif2);
+        System.out.println(objectif.toString());
+        System.out.println(objectif2.toString());
+        texte.lancer();
+        System.out.println("Mission accomplie");
+        texte.detach(objectif);
+
+    }
+}
diff --git a/src/main/java/fr/univlille/iut/r304/tp3/q2/Texte.java b/src/main/java/fr/univlille/iut/r304/tp3/q2/Texte.java
new file mode 100644
index 0000000000000000000000000000000000000000..6b4c5c4a7d239872b88965cb21ae7d9fe79cdf99
--- /dev/null
+++ b/src/main/java/fr/univlille/iut/r304/tp3/q2/Texte.java
@@ -0,0 +1,25 @@
+package fr.univlille.iut.r304.tp3.q2;
+
+import fr.univlille.iut.r304.tp3.q1.Observable;
+
+import java.io.InputStream;
+import java.util.Scanner;
+
+public class Texte extends Observable {
+    private InputStream IS;
+    protected Scanner scan;
+    private String text;
+    Texte(InputStream IS){
+        this.IS = IS;
+        this.text = "";
+    }
+
+    public void lancer(){
+        while (!text.equals("!fin")){
+            scan = new Scanner(IS);
+            text = scan.nextLine();
+            this.notifyObservers(text);
+        }
+        scan.close();
+    }
+}
diff --git a/src/main/java/fr/univlille/iut/r304/tp3/q3/ConnectableProperty.java b/src/main/java/fr/univlille/iut/r304/tp3/q3/ConnectableProperty.java
index ce7269d5ecfe5adf17694c31683a359b9322d7ca..ad0c3bd89c5cf76c84cc0178974879ad4f73b027 100644
--- a/src/main/java/fr/univlille/iut/r304/tp3/q3/ConnectableProperty.java
+++ b/src/main/java/fr/univlille/iut/r304/tp3/q3/ConnectableProperty.java
@@ -1,14 +1,35 @@
 package fr.univlille.iut.r304.tp3.q3;
 
-public class ConnectableProperty extends ObservableProperty {
+import fr.univlille.iut.r304.tp3.q1.Observable;
+import fr.univlille.iut.r304.tp3.q1.Observer;
+
+public class ConnectableProperty extends ObservableProperty implements Observer {
 
 	public void connectTo(ConnectableProperty other) {
+		other.attach(this);
+		other.notifyObservers(other.getValue());
 	}
 
 	public void biconnectTo(ConnectableProperty other) {
+		other.attach(this);
+		other.notifyObservers(other.getValue());
+		this.attach(other);
+		this.notifyObservers(this.getValue());
+
 	}
 
 	public void unconnectFrom(ConnectableProperty other) {
+		other.detach(this);
 	}
 
+	@Override
+	public void update(Observable subj) {
+	}
+
+	@Override
+	public void update(Observable subj, Object data) {
+		if (this.getValue() != data) {
+			this.setValue(data);
+		}
+	}
 }
diff --git a/src/main/java/fr/univlille/iut/r304/tp3/q3/ObservableProperty.java b/src/main/java/fr/univlille/iut/r304/tp3/q3/ObservableProperty.java
index 4fe250c1b28a1036c86d634bbc124f6a0e51fd4c..d3d1f896c7fc172b159072aa61b5aa010c6c30bd 100644
--- a/src/main/java/fr/univlille/iut/r304/tp3/q3/ObservableProperty.java
+++ b/src/main/java/fr/univlille/iut/r304/tp3/q3/ObservableProperty.java
@@ -1,24 +1,17 @@
 package fr.univlille.iut.r304.tp3.q3;
 
+import fr.univlille.iut.r304.tp3.q1.Observable;
 import fr.univlille.iut.r304.tp3.q1.Observer;
 
-public class ObservableProperty {
-
+public class ObservableProperty extends Observable {
+	protected Object property;
 	public void setValue(Object i) {
+		property = i;
+		this.notifyObservers(property);
 	}
 
 	public Object getValue() {
-		return null;
-	}
-
-	public void attach(Observer observer) {
-		// methode cree pour que les tests compilent sans erreur
-		// n'est pas censée rester une fois que vous avez fini Q2.1
-	}
-
-	public void detach(Observer observer) {
-		// methode cree pour que les tests compilent sans erreur
-		// n'est pas censée rester une fois que vous avez fini Q2.1
+		return property;
 	}
 
 }
diff --git a/src/main/java/fr/univlille/iut/r304/tp3/q4/Devise.java b/src/main/java/fr/univlille/iut/r304/tp3/q4/Devise.java
new file mode 100644
index 0000000000000000000000000000000000000000..af7d66683b9951cf0e41a9208d076ed1f6a761d1
--- /dev/null
+++ b/src/main/java/fr/univlille/iut/r304/tp3/q4/Devise.java
@@ -0,0 +1,72 @@
+package fr.univlille.iut.r304.tp3.q4;
+
+import fr.univlille.iut.r304.tp3.q3.ConnectableProperty;
+
+public class Devise extends ConnectableProperty {
+    private String nom;
+    private double tauxDeChange;
+
+    public Devise(String nom, double tauxDeChange) {
+        this.nom = nom;
+        this.tauxDeChange = tauxDeChange;
+    }
+
+    @Override
+    public void update(Observable subj, Object data) {
+        if (subj instanceof Devise) {
+            Devise autreDevise = (Devise) subj;
+            if (this.nom.equals("Euros")) {
+                // Conversion de dollars à euros
+                double montantEnDollars = (double) data;
+                double montantEnEuros = montantEnDollars / tauxDeChange;
+                this.setValue(montantEnEuros);
+            } else if (this.nom.equals("Dollars")) {
+                // Conversion d'euros à dollars
+                double montantEnEuros = (double) data;
+                double montantEnDollars = montantEnEuros * tauxDeChange;
+                this.setValue(montantEnDollars);
+            }
+        }
+    }
+
+    public String getNom() {
+        return nom;
+    }
+
+    public double getTauxDeChange() {
+        return tauxDeChange;
+    }
+
+    public static void main(String[] args) {
+        // Taux de change: 1 Euro = 1.1 Dollars
+        Devise euros = new Devise("Euros", 1.1);
+        Devise dollars = new Devise("Dollars", 1 / 1.1);
+
+        // Connexion des devises
+        euros.biconnectTo(dollars);
+
+        // Ajout de 20$
+        dollars.setValue(20.0);
+        System.out.println("Ajout 20$");
+        System.out.println(euros.getValue() + " €");
+        System.out.println(dollars.getValue() + " $");
+
+        // Retrait de 11€
+        euros.setValue(euros.getValue() - 11);
+        System.out.println("Retrait 11€");
+        System.out.println(euros.getValue() + " €");
+        System.out.println(dollars.getValue() + " $");
+
+        // Ajout d'une troisième devise : Yen
+        Devise yen = new Devise("Yen", 0.0075); // 1 Euro = 133.33 Yen
+        euros.biconnectTo(yen);
+        yen.biconnectTo(euros);
+
+        // Ajout de 1000 Yen
+        yen.setValue(1000.0);
+        System.out.println("Ajout 1000 Yen");
+        System.out.println(euros.getValue() + " €");
+        System.out.println(dollars.getValue() + " $");
+        System.out.println(yen.getValue() + " Yen");
+    }
+}
\ No newline at end of file