youtube의 디자인 패턴 강의를 보면서 정리함. 소스위주
https://www.youtube.com/watch?v=UEjsbd3IZvA&index=1&list=PLsoscMhnRc7pPsRHmgN4M8tqUdWZzkpxY
소스 출처
https://bitbucket.org/garampark/java-design-pattern/src/ed39c43449f60428450e8c647d05f77f2f642ef1/Chapter08-AbstractFactory-2/src/Main.java?at=master&fileviewer=file-view-default
소스는 일부 수정함
각 챕터별로 한눈에 보기 위해 1개의 class 파일에 다 넣음.
1장
/** * 디자인 패턴을 사용하는 이유는 협업을 위해서 * 내 의도의 틀 안에서 상대방이 다음 코드를 원활하게 작성할 수 있도록 하기 위해 * 오픈소스 라이브러리 배포 jar 환경이기 때문에 가능한듯 */ /** * 01. strategy : 전략 바꾸기 */ interface Weapon { void attack(); } class Knife implements Weapon { @Override public void attack() { System.out.println("Knife"); } } class Sword implements Weapon { @Override public void attack() { System.out.println("Sword"); } } class Character { private Weapon w; public Character(Weapon w) { this.w = w; } public void attack() { w.attack(); // 위임 } } public class _01_Main { public static void main(String[] args) { Character character1 = new Character(new Knife()); // 전략1 character1.attack(); Character character2 = new Character(new Sword()); // 전략2 character2.attack(); } }
2장
/** * 02. adapter : 연관성 없는 두 객체 묶어 사용하기 * 기존 라이브러리를 바로 실행하지 않고, 한번 거쳐서 사용하기 */ class ExistLibrary { public static double twoTime(double num) { return num * 2; } public static double half(double num) { return num / 2; } } interface Adapter { float twoTime(float f); float half(float f); } class AdapterImpl implements Adapter { @Override public float twoTime(float f) { System.out.println("로그 찍기"); return (float) ExistLibrary.twoTime(f); } @Override public float half(float f) { return (float) ExistLibrary.half(f); } } public class _02_Main { public static void main(String[] args) { AdapterImpl adapterImpl = new AdapterImpl(); float result1 = adapterImpl.twoTime(12.2f); float result2 = adapterImpl.twoTime(1.2f); System.out.println(result1); System.out.println(result2); } }
3장
/** * 03. template : 공통적인 프로세스를 묶어주기 * 모양자 * 알고리즘의 구조(순서)를 메소드에 정의하고 * 하위 클래스에서 알고리즘 구조의 변경없이 * 알고리즘을 재정의 하는 패턴 */ abstract class Helper { // 같은 패키지에서만 보이도록 protected abstract String doA(String s); protected abstract boolean doB(String s); protected abstract int doC(String s); protected abstract String doD(String s); protected abstract String doE(String s); // 알고리즘 구조 public String request(String s) { // step1 String a = doA(s); // step2 if (doB(a)) { throw new Error("EEEE"); } // step3 int i = doC(s); if (i > 0) { // step4 doD(s); } // step5 return doE(s); } } class ImplHelper extends Helper { @Override protected String doA(String s) { // TODO 구현 필요 return null; } @Override protected boolean doB(String s) { // TODO return false; } @Override protected int doC(String s) { // TODO return 0; } @Override protected String doD(String s) { // TODO return null; } @Override protected String doE(String s) { // TODO return null; } } public class _03_Main { public static void main(String[] args) { ImplHelper h = new ImplHelper(); h.request("ID"); } }
4장
/** * 04. factory : 생성의 템플릿 메소드 패턴(템플릿을 이용해서 팩토리 구현) */ interface Item { void use(); } class HpPotion implements Item { @Override public void use() { System.out.println("HP회복"); } } class MpPotion implements Item { @Override public void use() { System.out.println("MP회복"); } } abstract class ItemCreator { public Item create() { // step1 requestItemInfo(); // step2 Item item = createItem(); return item; } abstract protected void requestItemInfo(); abstract protected Item createItem(); } class HpCreator extends ItemCreator { @Override protected void requestItemInfo() { // TODO Auto-generated method stub } @Override protected Item createItem() { // TODO Auto-generated method stub return new HpPotion(); } } class MpCreator extends ItemCreator { @Override protected void requestItemInfo() { // TODO Auto-generated method stub } @Override protected Item createItem() { // TODO Auto-generated method stub return new MpPotion(); } } public class _04_Main { public static void main(String[] args) { ItemCreator creator = new HpCreator(); Item item1 = creator.create(); item1.use(); ItemCreator creator2 = new MpCreator(); Item item2 = creator2.create(); item2.use(); } }
5장
/** * 05. singleton : 하나의 인스턴스만 있도록 하기 */ class Speaker { static private Speaker instance; public Speaker() { } public static Speaker getInstance() { if (instance == null) { instance = new Speaker(); System.out.println("새로생성"); }else { System.out.println("이미생성"); } return instance; } } public class _05_Main { public static void main(String[] args) { Speaker instance1 = Speaker.getInstance(); Speaker instance2 = Speaker.getInstance(); System.out.println(instance1.hashCode()); System.out.println(instance2.hashCode()); } }
6장
import lombok.Getter; import lombok.Setter; import lombok.ToString; /** * 06. 프로토타입 : 생산 비용 줄이기 (복잡한 인스턴스 복사하기) */ @Setter @Getter @ToString class Path implements Cloneable { // deep copy를 위해서 준비 private int i; public Path(int i) { this.i = i; } // super.clone이 protected이므로, Path에 public clone 함수로 감싸줘야 한다. Adapter느낌 public Path clone() throws CloneNotSupportedException { return (Path) super.clone(); } } @Setter @Getter @ToString class Shape implements Cloneable { private String id; } @Setter @Getter @ToString class Circle extends Shape { private int x, y, r; private Path path; public Circle(int x, int y, int r, Path path) { super(); this.x = x; this.y = y; this.r = r; this.path = path; } public void setPathI(int i) { this.path.setI(i); } public Circle copy() throws CloneNotSupportedException { Circle circle = (Circle) super.clone(); // 숫자, 문자만? 얕은복사만 circle.setPath(this.path.clone()); circle.x += 1; circle.y += 1; return circle; } } public class _06_Main { public static void main(String[] args) throws CloneNotSupportedException { Circle circle1 = new Circle(1,2,3,new Path(4)); Circle circle2 = circle1.copy(); circle1.setX(3); circle1.setPathI(2); System.out.println(circle1.getX() + ", " + circle1.getPath()); System.out.println(circle2.getX() + ", " + circle2.getPath()); } }
7장-1
import lombok.Getter; import lombok.Setter; import lombok.ToString; /** * 07. 빌더 : 복잡한 단계가 필요한 인스턴스 생성을 빌더패턴을 통해서 구현할 수 있다. (템플릿과 비슷) * 복잡한 단계를 거쳐야 생성되는 객체의 구현을 서브클래스에게 넘겨주는 패턴 */ @Setter @Getter @ToString class Computer { private String cpu; private String ram; private String storage; public Computer(String cpu, String ram, String storage) { super(); this.cpu = cpu; this.ram = ram; this.storage = storage; } } abstract class BluePrint { abstract public void setCpu(); abstract public void setRam(); abstract public void setStorage(); abstract public Computer getComputer(); } class LgGramBlueprint extends BluePrint{ private Computer computer; public LgGramBlueprint() { computer = new Computer("default", "default", "default"); } @Override public void setCpu() { computer.setCpu("i7"); } @Override public void setRam() { computer.setRam("8g"); } @Override public void setStorage() { computer.setStorage("256g ssd"); } @Override public Computer getComputer() { return this.computer; } } //class HPBlueprint extends BluePrint{... class Factory { private BluePrint print; public void setBlueprint(BluePrint print) { this.print = print; } public void make() { print.setCpu(); print.setRam(); print.setStorage(); } public Computer getComputer() { return print.getComputer(); } } public class _07_1_Main { public static void main(String[] args) { Factory factory = new Factory(); factory.setBlueprint(new LgGramBlueprint()); factory.make(); Computer computer = factory.getComputer(); System.out.println(computer); } }
7장-2
import lombok.Getter; import lombok.Setter; import lombok.ToString; /** * 07. 빌더2 : 많은 인자를 가진 객체의 생성을 * 다른 객체의 도움으로 생성하는 패턴 */ @Setter @Getter @ToString class Computer2 { private String cpu; private String ram; private String storage; public Computer2(String cpu, String ram, String storage) { super(); this.cpu = cpu; this.ram = ram; this.storage = storage; } } class ComputerBuiler { private Computer2 computer; public ComputerBuiler() { computer = new Computer2("default", "default", "default"); } public static ComputerBuiler startWithCpu(String cpu) { ComputerBuiler builder = new ComputerBuiler(); builder.computer.setCpu(cpu); return builder; } public ComputerBuiler setRam(String ram) { computer.setRam(ram); return this; } public ComputerBuiler setStorage(String storage) { computer.setStorage(storage); return this; } public Computer2 build() { return computer; } } public class _07_2_Main { public static void main(String[] args) { Computer2 computer = ComputerBuiler.startWithCpu("i7") .setRam("8g") .setStorage("256g ssd") .build(); System.out.println(computer); } }
8장-1
/** * Abstract Factory : 객체 생성의 가상화 */ interface Body { } interface Wheel { } class SamBody implements Body { } class SamWheel implements Wheel { } interface BikeFactory { Body createBody(); Wheel createWheel(); } class SamBikeFactory implements BikeFactory { @Override public Body createBody() { return new SamBody(); } @Override public Wheel createWheel() { return new SamWheel(); } } //class GTBikeFactory implements BikeFactory { ... public class _08_1_Main { public static void main(String[] args) { BikeFactory factory = new SamBikeFactory(); Body body = factory.createBody(); Wheel wheel = factory.createWheel(); System.out.println(body); System.out.println(wheel); } }
8장-2
/** * Abstract Factory2 */ interface Button { public void click(); } interface TextArea { public String getText(); } interface GuiFac { public Button createButton(); public TextArea createTextArea(); } class LinuxButton implements Button { @Override public void click() { System.out.println("리눅스 버튼 "); } } class LinuxTextArea implements TextArea { @Override public String getText() { return "리눅스 텍스트에어리어"; } } class LinuxGuiFac implements GuiFac { @Override public Button createButton() { // return new LinuxButton(); } @Override public TextArea createTextArea() { return new LinuxTextArea(); } } //class MacButton implements Button { //class MacTextArea implements TextArea { //class MacGutFac implements GuiFac { //class WinButton implements Button { //class WinTextArea implements TextArea { //class WinGutFac implements GuiFac { class FactoryInstance { public static GuiFac getGuiFac() { switch (1) { // TODO if case 0: // return new MacGutFac(); case 1: return new LinuxGuiFac(); case 2: // return new WinGutFac(); } return null; } } public class _08_2_Main { public static void main(String[] args) { GuiFac fac = FactoryInstance.getGuiFac(); Button button = fac.createButton(); TextArea area = fac.createTextArea(); button.click(); System.out.println(area.getText()); System.out.println(System.getProperty("os.name")); } }
9장
/** * 09. 브릿지 - 기능 계층과 구현 계층의 분리 */ interface MorseCodeFunction { public void dot(); public void dash(); public void space(); } class FlashMCF implements MorseCodeFunction{ @Override public void dot() { System.out.print(" 번쩍 "); } @Override public void dash() { System.out.print(" 반짝 "); } @Override public void space() { System.out.print(" - "); } } class DefaultMCF implements MorseCodeFunction { @Override public void dot() { System.out.print("·"); } @Override public void dash() { System.out.print("-"); } @Override public void space() { System.out.print(" "); } } class MorseCode { private MorseCodeFunction function; public MorseCode(MorseCodeFunction function) { this.function = function; } public void setFunction(MorseCodeFunction function) { this.function = function; } public void dot() { function.dot(); } public void dash() { function.dash(); } public void space() { function.space(); } } class PrintMorseCode extends MorseCode { public PrintMorseCode(MorseCodeFunction function) { super(function); // !! } public PrintMorseCode g() { dash(); dash(); dot(); space(); return this; } public PrintMorseCode a() { dot(); dash(); space(); return this; } public PrintMorseCode r() { dot(); dash(); dot(); space(); return this; } public PrintMorseCode m() { dash(); dash(); space(); return this; } } public class _09_Main { public static void main(String[] args) { PrintMorseCode code = new PrintMorseCode(new FlashMCF()); code.g().a().r().a().m(); } }
10장
import java.util.ArrayList; import java.util.List; import lombok.Getter; import lombok.Setter; /** * 10. composite - tree 구조, 컨테이너와 내용물을 같게 다루기 */ @Getter @Setter abstract class Component { private String name; public Component(String name) { this.name = name; } } class Folder extends Component { Listchildren = new ArrayList<>(); public Folder(String name) { super(name); } public boolean addComponent(Component component) { return children.add(component); } public boolean removeComponet(Component component) { return children.remove(component); } public List getChildren() { return children; } } @Getter @Setter class File extends Component { private Object data; public File(String name) { super(name); } } public class _10_Main { public static void main(String[] args) { Folder root = new Folder("root"); Folder home = new Folder("home"); Folder garam = new Folder("garam"); Folder music = new Folder("music"); Folder picture = new Folder("picture"); Folder doc = new Folder("doc"); Folder usr = new Folder("usr"); File track1 = new File("track1"); File track2 = new File("track2"); File pic1 = new File("pic1"); File doc1 = new File("doc1"); File java = new File("java"); root.addComponent(home); home.addComponent(garam); garam.addComponent(music); music.addComponent(track1); music.addComponent(track2); garam.addComponent(picture); picture.addComponent(pic1); garam.addComponent(doc); doc.addComponent(doc1); root.addComponent(usr); usr.addComponent(java); show(" ", root); } private static void show(String tab, Component component) { System.out.println(tab + component.getClass().getName() + "|" + component.getName()); if (component instanceof Folder) { for (Component c : ((Folder) component).getChildren()) { show(tab + " ", c); // 재귀 } } } }
console결과:
Folder|root
Folder|home
Folder|garam
Folder|music
File|track1
File|track2
Folder|picture
File|pic1
Folder|doc
File|doc1
Folder|usr
File|java
11장
import java.util.Scanner; /** * 11. decorator : 동적으로 책임 추가 */ interface IBeverage { int getTotalPrice(); } class Base implements IBeverage { @Override public int getTotalPrice() { return 0; } } abstract class AbstAdding implements IBeverage { private IBeverage base; public AbstAdding(IBeverage base) { super(); this.base = base; } protected IBeverage getBase() { return base; } @Override public int getTotalPrice() { return base.getTotalPrice(); } } class Espresso extends AbstAdding { static protected int espressoCount = 0; public Espresso(IBeverage meterial) { super(meterial); } private static int getAddPrice(){ espressoCount += 1; int addPrice = 100; if (espressoCount > 1) { addPrice = 70; } return addPrice; } @Override public int getTotalPrice() { return super.getTotalPrice() + getAddPrice(); } } class Milk extends AbstAdding { public Milk(IBeverage meterial) { super(meterial); } @Override public int getTotalPrice() { return super.getTotalPrice() + 50; } } public class _11_Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); // base IBeverage beverage = new Base(); // base에서 시작 boolean done = false; while (!done) { System.out.println("음료 현재 가격 : " + beverage.getTotalPrice()); System.out.print("선택 : 1:샷 추가 / 2:우유 추가"); switch (sc.nextInt()) { case 0: done = true; break; case 1: beverage = new Espresso(beverage); // 지금까지의 beverage를 포함해서 다시 객체 생성 break; case 2: beverage = new Milk(beverage); break; } } System.out.println("음료 가격 : " + beverage.getTotalPrice()); sc.close(); } }
12장
import java.util.ArrayList; import lombok.Getter; import lombok.Setter; /** * 12. visitor 방문자 - 객체에서 처리 분리하기 */ // Visitor <-> Visitable interface Visitor { public void visit(Place visitable); } interface Place { public void accept(Visitor visitor); } @Getter @Setter class VisitorImpl implements Visitor { private int number; public VisitorImpl() { this.number = 0; } @Override public void visit(Place place) { if(place instanceof PlaceImpl){ number += ((PlaceImpl) place).getNumberOfMember(); }else { //... } } } @Getter @Setter class PlaceImpl implements Place { private int numberOfMember; public PlaceImpl(int numberOfMember) { this.numberOfMember = numberOfMember; } @Override public void accept(Visitor visitor) { visitor.visit(this); // visitor 에게 나 자신을 방문하도록 허락한다. } } public class _12_Main { public static void main(String[] args) { ArrayListplaceList = new ArrayList (); placeList.add(new PlaceImpl(1)); placeList.add(new PlaceImpl(2)); placeList.add(new PlaceImpl(3)); placeList.add(new PlaceImpl(4)); placeList.add(new PlaceImpl(5)); VisitorImpl visitorImpl = new VisitorImpl(); for (Place place : placeList) { place.accept(visitorImpl); } System.out.println(visitorImpl.getNumber()); } }
13장-1
import lombok.Getter; import lombok.Setter; /** * 13. chain of responsibility 책임 사슬 */ @Getter @Setter class Request { private int a, b; private String operator; public Request(int a, int b, String operator) { super(); this.a = a; this.b = b; this.operator = operator; } } abstract class Calculator { private Calculator nextCaculator; public void setNextCalculator(Calculator nextCaculator) { this.nextCaculator = nextCaculator; } public boolean process(Request request) { if (operator(request)) { return true; } else { if (nextCaculator != null) return nextCaculator.operator(request); } return false; // if (preCaculator != null) // if(preCaculator.process(request)) // return true; // // return operator(request); } abstract protected boolean operator(Request request); } class PlusCalculator extends Calculator { @Override protected boolean operator(Request request) { if (request.getOperator().equals("+")) { int a = request.getA(); int b = request.getB(); int result = a + b; System.out.println(a + "+" + b + "=" + result); } return false; } } class SubCalculator extends Calculator { @Override protected boolean operator(Request request) { if (request.getOperator().equals("-")) { int a = request.getA(); int b = request.getB(); int result = a - b; System.out.println(a + "-" + b + "=" + result); } return false; } } public class _13_1_Main { public static void main(String[] args) { Calculator plus = new PlusCalculator(); Calculator sub = new SubCalculator(); plus.setNextCalculator(sub); Request request1 = new Request(1, 2, "+"); // 3 Request request2 = new Request(10, 2, "-");// 8 plus.process(request1); plus.process(request2); } }
13장-2
import lombok.Getter; import lombok.Setter; /** * 13. chain of responsibility 책임 사슬 advanced */ interface Defense { public void depense(Attack attack); } @Getter @Setter class Attack { private int amount; } abstract class Armor implements Defense { private Defense nextDefense; public void setNextArmor(Defense nextDefense) { this.nextDefense = nextDefense; } @Override public void depense(Attack attack) { proccess(attack); if (nextDefense != null) nextDefense.depense(attack); } abstract protected void proccess(Attack attack); } public class _13_2_Main { public static void main(String[] args) { Attack attack = new Attack(); attack.setAmount(100); Armor armorA = new Armor() { @Override protected void proccess(Attack attack) { int amount = attack.getAmount(); amount *= 0.8; attack.setAmount(amount); } }; Armor armorB = new Armor() { @Override protected void proccess(Attack attack) { int amount = attack.getAmount(); amount -= 10; if (amount < 0) amount = 0; attack.setAmount(amount); } }; armorA.setNextArmor(armorB); armorA.depense(attack); System.out.println(attack.getAmount()); armorA.setNextArmor(new Armor() { @Override protected void proccess(Attack attack) { int amount = attack.getAmount(); amount -= 50; if (amount < 0) amount = 0; attack.setAmount(amount); } }); attack.setAmount(100); armorA.depense(attack); System.out.println(attack.getAmount()); } }
14장
/** * 14 facade 퍼사드 : 복잡한 과정을 간단하게 제공 */ class HelpSystem1 { public HelpSystem1() { System.out.println("Call Constructor : " + getClass().getSimpleName()); } public void process(){ System.out.println("Call Process : "+ getClass().getSimpleName()); } } class HelpSystem2 { public HelpSystem2() { System.out.println("Call Constructor : " + getClass().getSimpleName()); } public void process(){ System.out.println("Call Process : "+ getClass().getSimpleName()); } } class HelpSystem3 { public HelpSystem3() { System.out.println("Call Constructor : " + getClass().getSimpleName()); } public void process(){ System.out.println("Call Process : "+ getClass().getSimpleName()); } } class Facade { private HelpSystem1 helpSystem01; private HelpSystem2 helpSystem02; private HelpSystem3 helpSystem03; public Facade() { helpSystem01 = new HelpSystem1(); helpSystem02 = new HelpSystem2(); helpSystem03 = new HelpSystem3(); } public void process(){ helpSystem01.process(); helpSystem02.process(); helpSystem03.process(); } } public class _14_Main { public static void main(String[] args) { Facade facade = new Facade(); facade.process(); } }
15장-1
/** * 15. observer 상태 변화 관찰하기 */ interface OnClickListener { public void onClick(Button2 button); } class Button2 { private OnClickListener onClickListener; public void setOnClickListener(OnClickListener onClickListener) { this.onClickListener = onClickListener; } public void onClick() { // 이벤트 처리 if (onClickListener != null) onClickListener.onClick(this); } } public class _15_1_Main { public static void main(String[] args) { Button2 button = new Button2(); button.setOnClickListener(new OnClickListener() { @Override public void onClick(Button2 button) { System.out.println(button + " is Clicked"); } }); button.onClick(); } }
15장-2
import java.util.Observable; import java.util.Observer; /** * 15 observer2 */ class Button3 extends Observable{ public void onClick(){ setChanged(); // Observable notifyObservers(); // Observable // -------> update가 호출됨 } } public class _15_2_Main { public static void main(String[] args) { Button3 button = new Button3(); button.addObserver(new Observer() { @Override public void update(Observable o, Object arg) { System.out.println(o + " is Clicked"); } }); button.onClick(); button.onClick(); button.onClick(); } }
15장-3
import java.util.Vector;
/**
* 15. observer3 - 직접구현
*/
class Button4 {
private Observable observable;
public Button4() {
observable = new Observable();
}
public void addObserver(Observer o) {
observable.addObserver(o);
}
public void notifyObservers() {
observable.notifyObservers(null);
}
public void onClick() {
observable.setChanged();
notifyObservers();
}
}
interface Observer {
/**
* This method is called whenever the observed object is changed. An application
* calls an Observable object's notifyObservers
method to
* have all the object's observers notified of the change.
*
* @param o
* the observable object.
* @param arg
* an argument passed to the notifyObservers
method.
*/
void update(Observable o, T arg);
}
class Observable {
private boolean changed = false;
private Vector> obs;
/** Construct an Observable with zero Observers. */
public Observable() {
obs = new Vector<>();
}
/**
* Adds an observer to the set of observers for this object, provided that it is
* not the same as some observer already in the set. The order in which
* notifications will be delivered to multiple observers is not specified. See
* the class comment.
*
* @param o
* an observer to be added.
* @throws NullPointerException
* if the parameter o is null.
*/
public synchronized void addObserver(Observer o) {
if (o == null)
throw new NullPointerException();
if (!obs.contains(o)) {
obs.addElement(o);
}
}
/**
* Deletes an observer from the set of observers of this object. Passing
* null
to this method will have no effect.
*
* @param o
* the observer to be deleted.
*/
public synchronized void deleteObserver(Observer o) {
obs.removeElement(o);
}
/**
* If this object has changed, as indicated by the hasChanged
* method, then notify all of its observers and then call the
* clearChanged
method to indicate that this object has no longer
* changed.
*
* Each observer has its update
method called with two arguments:
* this observable object and null
. In other words, this method is
* equivalent to:
* notifyObservers(null)
*
* @see java.util.Observable#clearChanged()
* @see java.util.Observable#hasChanged()
* @see java.util.Observer#update(java.util.Observable, java.lang.Object)
*/
public void notifyObservers() {
notifyObservers(null);
}
/**
* If this object has changed, as indicated by the hasChanged
* method, then notify all of its observers and then call the
* clearChanged
method to indicate that this object has no longer
* changed.
*
* Each observer has its update
method called with two arguments:
* this observable object and the arg
argument.
*
* @param arg
* any object.
* @see java.util.Observable#clearChanged()
* @see java.util.Observable#hasChanged()
* @see java.util.Observer#update(java.util.Observable, java.lang.Object)
*/
public void notifyObservers(T arg) {
/*
* a temporary array buffer, used as a snapshot of the state of current
* Observers.
*/
Vector> arrLocal;
synchronized (this) {
/*
* We don't want the Observer doing callbacks into arbitrary code while holding
* its own Monitor. The code where we extract each Observable from the Vector
* and store the state of the Observer needs synchronization, but notifying
* observers does not (should not). The worst result of any potential
* race-condition here is that: 1) a newly-added Observer will miss a
* notification in progress 2) a recently unregistered Observer will be wrongly
* notified when it doesn't care
*/
if (!changed)
return;
arrLocal = (Vector>) obs.clone();
clearChanged();
}
for (Observer observer : arrLocal) {
observer.update(this, arg);
}
}
/**
* Clears the observer list so that this object no longer has any observers.
*/
public synchronized void deleteObservers() {
obs.removeAllElements();
}
/**
* Marks this Observable object as having been changed; the
* hasChanged method will now return true.
*/
public synchronized void setChanged() {
changed = true;
}
/**
* Indicates that this object has no longer changed, or that it has already
* notified all of its observers of its most recent change, so that the
* hasChanged method will now return false. This method is
* called automatically by the notifyObservers
methods.
*
* @see java.util.Observable#notifyObservers()
* @see java.util.Observable#notifyObservers(java.lang.Object)
*/
protected synchronized void clearChanged() {
changed = false;
}
/**
* Tests if this object has changed.
*
* @return true
if and only if the setChanged
method
* has been called more recently than the clearChanged
* method on this object; false
otherwise.
* @see java.util.Observable#clearChanged()
* @see java.util.Observable#setChanged()
*/
public synchronized boolean hasChanged() {
return changed;
}
/**
* Returns the number of observers of this Observable object.
*
* @return the number of observers of this object.
*/
public synchronized int countObservers() {
return obs.size();
}
}
public class _15_3_Main {
public static void main(String[] args) {
// 1. 제네릭
// 2. 델리케이트
// 3. 내부에 옵저버를 넣는다.
Button4 button = new Button4();
button.addObserver(new Observer() {
@Override
public void update(Observable o, String arg) {
System.out.println(o + " is clicked");
}
});
button.onClick();
button.onClick();
button.onClick();
}
}
15장-4
import java.util.Vector;
/**
* 15. observer4 - copy?
*/
class Button5 extends Observable2{
public void onClick(){
setChanged();
notifyObservers();
}
}
interface Observer2 {
/**
* This method is called whenever the observed object is changed. An
* application calls an Observable object's
* notifyObservers
method to have all the object's observers
* notified of the change.
*
* @param o
* the observable object.
* @param arg
* an argument passed to the notifyObservers
method.
*/
void update(Observable2 o, T arg);
}
class Observable2 {
private boolean changed = false;
private Vector> obs;
/** Construct an Observable with zero Observers. */
public Observable2() {
obs = new Vector<>();
}
/**
* Adds an observer to the set of observers for this object, provided
* that it is not the same as some observer already in the set.
* The order in which notifications will be delivered to multiple
* observers is not specified. See the class comment.
*
* @param o an observer to be added.
* @throws NullPointerException if the parameter o is null.
*/
public synchronized void addObserver(Observer2 o) {
if (o == null)
throw new NullPointerException();
if (!obs.contains(o)) {
obs.addElement(o);
}
}
/**
* Deletes an observer from the set of observers of this object.
* Passing null
to this method will have no effect.
* @param o the observer to be deleted.
*/
public synchronized void deleteObserver(Observer2 o) {
obs.removeElement(o);
}
/**
* If this object has changed, as indicated by the
* hasChanged
method, then notify all of its observers
* and then call the clearChanged
method to
* indicate that this object has no longer changed.
*
* Each observer has its update
method called with two
* arguments: this observable object and null
. In other
* words, this method is equivalent to:
*
* notifyObservers(null)
*
* @see java.util.Observable#clearChanged()
* @see java.util.Observable#hasChanged()
* @see java.util.Observer#update(java.util.Observable, java.lang.Object)
*/
public void notifyObservers() {
notifyObservers(null);
}
/**
* If this object has changed, as indicated by the
* hasChanged
method, then notify all of its observers
* and then call the clearChanged
method to indicate
* that this object has no longer changed.
*
* Each observer has its update
method called with two
* arguments: this observable object and the arg
argument.
*
* @param arg any object.
* @see java.util.Observable#clearChanged()
* @see java.util.Observable#hasChanged()
* @see java.util.Observer#update(java.util.Observable, java.lang.Object)
*/
public void notifyObservers(T arg) {
/*
* a temporary array buffer, used as a snapshot of the state of
* current Observers.
*/
Observer2[] arrLocal;
synchronized (this) {
/* We don't want the Observer doing callbacks into
* arbitrary code while holding its own Monitor.
* The code where we extract each Observable from
* the Vector and store the state of the Observer
* needs synchronization, but notifying observers
* does not (should not). The worst result of any
* potential race-condition here is that:
* 1) a newly-added Observer will miss a
* notification in progress
* 2) a recently unregistered Observer will be
* wrongly notified when it doesn't care
*/
if (!changed)
return;
// arrLocal = (Observer2[]) obs.toArray(); // 에러난다
arrLocal = new Observer2[obs.size()];
obs.toArray(arrLocal);
clearChanged();
}
for (int i = arrLocal.length-1; i>=0; i--)
((Observer2)arrLocal[i]).update(this, arg);
}
/**
* Clears the observer list so that this object no longer has any observers.
*/
public synchronized void deleteObservers() {
obs.removeAllElements();
}
/**
* Marks this Observable object as having been changed; the
* hasChanged method will now return true.
*/
protected synchronized void setChanged() {
changed = true;
}
/**
* Indicates that this object has no longer changed, or that it has
* already notified all of its observers of its most recent change,
* so that the hasChanged method will now return false.
* This method is called automatically by the
* notifyObservers
methods.
*
* @see java.util.Observable#notifyObservers()
* @see java.util.Observable#notifyObservers(java.lang.Object)
*/
protected synchronized void clearChanged() {
changed = false;
}
/**
* Tests if this object has changed.
*
* @return true
if and only if the setChanged
* method has been called more recently than the
* clearChanged
method on this object;
* false
otherwise.
* @see java.util.Observable#clearChanged()
* @see java.util.Observable#setChanged()
*/
public synchronized boolean hasChanged() {
return changed;
}
/**
* Returns the number of observers of this Observable object.
*
* @return the number of observers of this object.
*/
public synchronized int countObservers() {
return obs.size();
}
}
public class _15_4_Main {
public static void main(String[] args) {
Button5 button = new Button5();
button.addObserver(new Observer2() {
@Override
public void update(Observable2 o, Object arg) {
System.out.println(o + "is Clicked");
}
});
button.onClick();
button.onClick();
button.onClick();
}
}
16장
import java.util.ArrayList; import java.util.List; /** * 16. mediator 중재자 */ abstract class Colleague { private Mediator mediator; public boolean join(Mediator mediator) { if (mediator == null) return false; this.mediator = mediator; return mediator.addColleague(this); } public void sendData(String data) { if (mediator != null) mediator.mediate(data); } abstract public void handle(String data); } class ChatColleague extends Colleague { @Override public void handle(String data) { System.out.println(this+"-"+data); } } abstract class Mediator { protected Listcolleagues; public Mediator() { colleagues = new ArrayList<>(); } public boolean addColleague(Colleague colleague) { if (colleagues != null) return colleagues.add(colleague); else return false; } public abstract void mediate(String data); } class ChatMediator extends Mediator { @Override public void mediate(String data) { for (Colleague colleague : colleagues) { //중재가능성. colleague.handle(data); // 중재자가 보유한 colleague list에 모두 발송함 } } } public class _16_Main { public static void main(String[] args) { Mediator mediator = new ChatMediator(); Colleague colleague1 = new ChatColleague(); Colleague colleague2 = new ChatColleague(); Colleague colleague3 = new ChatColleague(); colleague1.join(mediator); colleague2.join(mediator); colleague3.join(mediator); colleague1.sendData("AAA"); colleague2.sendData("BBB"); colleague3.sendData("CCC"); } }
17장
/** * 17. state - 상태패턴, 상태를 객체로 나타내기 (변화가 생긴경우만 상태체크) */ interface LightState { void on(); void off(); } class Light { protected LightState lightState; private LightState offState = new LightState() { @Override public void on() { System.out.println("Light ON"); // off->on lightState = onState; } @Override public void off() { System.out.println("Nothing"); // off->off : nothing } }; private LightState onState = new LightState() { @Override public void on() { System.out.println("Nothing"); // on->on : nothing } @Override public void off() { System.out.println("Light OFF"); // on->off lightState = offState; } }; public Light() { lightState = offState; } public void on() { lightState.on(); } public void off() { lightState.off(); } } public class _17_Main { public static void main(String[] args) { Light light = new Light(); light.off(); light.off(); light.off(); light.on(); light.on(); light.on(); light.off(); light.on(); light.off(); light.on(); light.off(); light.on(); } }
18장
import java.util.Stack; import lombok.Getter; import lombok.Setter; /** * 18. memento 상태저장하기 */ @Getter class Memento { String state; protected Memento(String state) { this.state = state; } } @Getter @Setter class Originator { String state; public Memento createMemento() { return new Memento(state); } public void restoreMement(Memento memento) { this.state = memento.getState(); } } public class _18_Main { public static void main(String[] args) { StackmementoStack = new Stack<>(); // FILO: first in last out Originator originator = new Originator(); originator.setState("state 1"); mementoStack.push(originator.createMemento()); // Memento memento = new Memento();//X // memento.getState();//X originator.setState("state 2"); mementoStack.push(originator.createMemento()); originator.setState("state 3"); mementoStack.push(originator.createMemento()); originator.setState("state Final"); mementoStack.push(originator.createMemento()); originator.restoreMement(mementoStack.pop()); System.out.println(originator.getState());// state Final originator.restoreMement(mementoStack.pop()); System.out.println(originator.getState());// state 3 originator.restoreMement(mementoStack.pop()); System.out.println(originator.getState());// state 2 originator.restoreMement(mementoStack.pop()); System.out.println(originator.getState());// state 1 } }
end
'Java > POJO' 카테고리의 다른 글
lang3.StringUtils 사용예 (0) | 2016.04.20 |
---|