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 Observableobservable; 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 thenotifyObservers
method. */ void update(Observableo, 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(Observero) { 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 andnull
. 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 thehasChanged
* 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 thearg
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. * * @returntrue
if and only if thesetChanged
method * has been called more recently than theclearChanged
* 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 thenotifyObservers
method. */ void update(Observable2o, 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(Observer2o) { obs.removeElement(o); } /** * If this object has changed, as indicated by the * hasChanged
method, then notify all of its observers * and then call theclearChanged
method to * indicate that this object has no longer changed. ** Each observer has its
update
method called with two * arguments: this observable object andnull
. 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 theclearChanged
method to indicate * that this object has no longer changed. ** Each observer has its
update
method called with two * arguments: this observable object and thearg
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. * * @returntrue
if and only if thesetChanged
* 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 |
---|