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 {
List children = 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) {
ArrayList placeList = 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 List colleagues;
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) {
Stack mementoStack = 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 |
|---|