반응형
import java.util.Vector;
import java.util.Iterator;
import java.util.Random;
interface Observer {
// NumberGenerator(관찰대상)가 “나의 내용이 갱신되었습니다.
// 표시도 갱신해주세요” 라고 관찰자에게 알려줄 때 호출하는 메소드
// 관찰자들이라면 다 따라야하는 메소드
public abstract void update(NumberGenerator generator);
}
class DigitObserver implements Observer {
public void update(NumberGenerator generator) {
System.out.println("DigitObserver:" + generator.getNumber()); // 관찰한 수를 ‘숫자’로 표시함
try {
// 출력한 후, 표시된 모습을 잘 알 수 있도록
// Thread.sleep( )을 이용하여 스피드를 늦춘다.
Thread.sleep(100); // (100/1000 = 0.1 초) 동안 CPU를 반환하고 쉬겠다는 뜻
} catch (InterruptedException e) {
}
}
}
class GraphObserver implements Observer {
// 관찰한 수를 ‘간단한 그래프’로 표시함
public void update(NumberGenerator generator) {
System.out.println("GraphObserver:" + generator.getNumber());
int count = generator.getNumber();
// count 만큼 별표를 출력한다.
for (int i = 0; i < count; i++) {
System.out.print("*");
}
System.out.println("");
try {
Thread.sleep(100); // (100/1000 = 0.1 초) 동안 CPU를 반환하고 쉬겠다는 뜻
} catch (InterruptedException e) {
}
}
}
class NamePrintObserver implements Observer {
private String name;
//생성자. 이름 등록
public NamePrintObserver(String name) {
this.name = name;
}
// 관찰한 수에 해당하는 name을 출력하여 표시함
public void update(NumberGenerator generator) {
System.out.println("NamePrintObserver:" + generator.getNumber());
int count = generator.getNumber();
// count 만큼 이름을 출력한다.
for (int i = 0 ; i < count ; i++) {
System.out.print(name);
}
System.out.println("");
try {
Thread.sleep(100); // (100/1000 = 0.1 초) 동안 CPU를 반환하고 쉬겠다는 뜻
} catch (InterruptedException e) {
}
}
}
// 수를 생성하는 클래스, 관찰대상을 대표하는 클래스
abstract class NumberGenerator {
// NumberGenerator를 관찰하고 있는 Observer들을 보관하고 있는 필드
private Vector observers = new Vector();
// Observer를 추가할 때 호출하는 메소드
public void addObserver(Observer observer) { // Observer를 추가
observers.add(observer);
}
// Observer를 삭제할 때 호출하는 메소드
public void deleteObserver(Observer observer) { // Observer를 삭제
observers.remove(observer);
}
// Observer 전원에게, “나의 내용이 갱신되었기 때문에
// 당신의 표시도 갱신해주세요”라고 알려주는 메소드
public void notifyObservers() {
Iterator it = observers.iterator();
// Observer들의 update(this) 메소드를 차례차례 호출한다.
while (it.hasNext()) {
Observer o = (Observer) it.next();
o.update(this);
}
}
public abstract int getNumber(); // 수를 취득한다.
public abstract void execute(); // 수를 생성한다.
}
// NumberGenerator의 하위 클래스
class PrimeNumberGenerator extends NumberGenerator {
// java.util.Random 클래스 이용
private int number; // 생성된 소수를 저장하는 변수
public int getNumber() { // 수를 취득한다.
return number; // number 필드의 값을 반환함
}
// 3~50 사이의 소수를 20개를 생성하고,
// 그 때마다 notifyObservers를 호출하여,
// 관찰자들에게 통지한다.
public void execute() {
for(int i = 0 ; i < 20 ; i++) {
number = getPrimeNumber(50);
notifyObservers(); // 관찰자에게 통지하라고 요청한다.
}
}
private int getPrimeNumber(int n) {
int num = -1;
do {
//3~n 사이의 소수를 구함
num = new Random().nextInt(n - 2) + 3;
} while(!isPrimeNumber(num));
return num;
}
private boolean isPrimeNumber(int n) {
//소수 확인 로직. 이정도로 했습니다. ㅡㅡ;;
for(int i = 2 ; i < n ; i++) {
if(n % i == 0) return false;
}
return true;
}
}
public class Main {
public static void main(String[] args) {
// PrimeNumberGenerator 인스턴스 생성
NumberGenerator png = new PrimeNumberGenerator();
// PrimeNumberGenerator에 관찰자 3개를 등록함
png.addObserver(new DigitObserver());
png.addObserver(new GraphObserver());
png.addObserver(new NamePrintObserver("NPO!"));
// PrimeNumberGenerator의 execute( )를 이용해서 수를 생성한다
png.execute();
// 소수가 발생될 때마다, 관찰자들은 각자의 방식대로 수를 ‘표시’한다.
}
}
반응형
'Design Pattern | Data structure' 카테고리의 다른 글
Transactional Outbox Pattern (아웃박스 패턴) (0) | 2023.06.18 |
---|---|
[Linked List] 중복값 삭제 (0) | 2020.07.08 |
[Liked List] 단방향 구현 (0) | 2020.07.07 |
[Linked List] 개념 (0) | 2020.07.07 |