Last active
November 30, 2018 06:27
-
-
Save billy-idle/115dabd9c27dd4ae7805e6e9b23e306b to your computer and use it in GitHub Desktop.
MVC "Push" Pattern from scratch.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package mvc.from.scratch.push; | |
import java.util.ArrayList; | |
import java.util.List; | |
import java.util.Random; | |
interface Observer<T> { | |
void update(T t); | |
} | |
public class MVCPushFromScratch { | |
public static void main(String[] args) { | |
// The Model doesn't know anything about the controller neither the view. | |
var rnm = new RandomNumberModel(); | |
// The Controller knows about the Model but not the View. | |
var rnc = new RandomNumberController(rnm); | |
// The View only knows about the Controller. | |
// The Model is pushing its data trough the Observer interface | |
var rnv = new RandomNumberView(rnc); | |
// The Model registers the View | |
rnm.registerObserver(rnv); | |
int i = 0; | |
while (i < 5) { | |
/* | |
Imagine that this could be an ActionEvent | |
triggered by some Button. i.e. "generateRandomNumberButton" | |
*/ | |
rnv.generateRandomNumber(); | |
i++; | |
} | |
/* | |
Output | |
1. 66 | |
2. 17 | |
3. 75 | |
4. 94 | |
5. 39 | |
*The output will vary because its randomness. | |
*/ | |
} | |
} | |
abstract class Subject<T> { | |
private List<Observer<T>> observers = new ArrayList<>(); | |
public void registerObserver(Observer<T> o) { | |
observers.add(o); | |
} | |
public void removeObserver(Observer<T> o) { | |
observers.remove(o); | |
} | |
protected void notifyObservers(T t) { | |
observers.forEach(o -> o.update(t)); | |
} | |
public void removeAllObservers() { | |
observers.clear(); | |
} | |
} | |
/** | |
* In general, in the MVC pattern all the dependencies point to the Model. | |
* The Model doesn't know anything about the controller neither the view. | |
*/ | |
class RandomNumberModel extends Subject<Integer> { | |
private Random random; | |
public RandomNumberModel() { | |
this.random = new Random(); | |
} | |
/** | |
* Generates an integer random number between 0 and 100, | |
* notifying and broadcasting its state to all the observers. | |
*/ | |
public void generateRandomNumber() { | |
var number = this.random.nextInt(101); | |
notifyObservers(number); | |
} | |
} | |
/** | |
* The Controller knows about the Model but not the View. | |
* Its main purpose is to send commands from the View to the Model. | |
* ("Commands" change the state of the system and return nothing) | |
*/ | |
class RandomNumberController { | |
private RandomNumberModel rnm; | |
public RandomNumberController(RandomNumberModel rnm) { | |
this.rnm = rnm; | |
} | |
/** | |
* Encapsulates the call. ("Tell", don't "Ask" Principle) | |
*/ | |
public void generateRandomNumber() { | |
this.rnm.generateRandomNumber(); | |
} | |
} | |
/** | |
* The View knows about the Controller but not the Model, or, at least | |
* the data type that is being pushed. | |
*/ | |
class RandomNumberView implements Observer<Integer> { | |
private RandomNumberController rnc; | |
private int position; | |
private int number; | |
public RandomNumberView(RandomNumberController rnc) { | |
this.rnc = rnc; | |
} | |
public void generateRandomNumber() { | |
this.rnc.generateRandomNumber(); | |
} | |
/** | |
* This is call when the Model calls notifyObservers() | |
*/ | |
public void update(Integer t) { | |
this.number = t; | |
this.updatePosition(); | |
this.printRandomNumber(); | |
} | |
private void updatePosition() { | |
this.position++; | |
} | |
private void printRandomNumber() { | |
System.out.printf("%-1d. %s%n", this.position, this.number); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Class Diagram - MVC "Push" Pattern From Scratch