Post

โ›“๏ธ Java Design-Pattern XV - Chain of Responsibility

โ›“๏ธ Java Design-Pattern XV - Chain of Responsibility

๐Ÿ“— ใ€ŽJAVA ์–ธ์–ด๋กœ ๋ฐฐ์šฐ๋Š” ๋””์ž์ธ ํŒจํ„ด : ์‰ฝ๊ฒŒ ๋ฐฐ์šฐ๋Š” GoF์˜ 23๊ฐ€์ง€ ๋””์ž์ธ ํŒจํ„ดใ€๋ฅผ ์ฝ๊ณ  ์ •๋ฆฌํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค.

Chain of Responsibility ํŒจํ„ด์ด๋ž€?

  • ์—ฌ๋Ÿฌ ๊ฐ์ฒด๋ฅผ ์‚ฌ์Šฌ์ฒ˜๋Ÿผ ์—ฐ์‡„์ ์œผ๋กœ ๋ฌถ๊ณ , ๊ฐ์ฒด ์‚ฌ์Šฌ์„ ์ฐจ๋ก€๋Œ€๋กœ ๋Œ๋ฉด์„œ ์›ํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ํŒจํ„ด์ด๋‹ค.
  • ์ฆ‰, ์–ด๋–ค ๊ฐ์ฒด์—๊ฒŒ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์œผ๋ฉด ์ฒ˜๋ฆฌํ•˜๊ณ , ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†์„ ๋•Œ๋Š” ๋‹ค๋ฅธ ๊ฐ์ฒด์—๊ฒŒ ๋„˜๊ธด๋‹ค.

์˜ˆ์ œ ํ”„๋กœ๊ทธ๋žจ

  • ํŠธ๋Ÿฌ๋ธ”์ด ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ํ•ด๊ฒฐํ•ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ์„ ๋‹ค์Œ ์˜ˆ์ œ ํ”„๋กœ๊ทธ๋žจ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

Troubleย ํด๋ž˜์Šค

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Trouble {
	private int number;
    
    public Trouble(int number) {
        this.number = number;
    }
    
    public int getNumber() {
        return number;
    }
    
    @Override
    public String toString() {
        return "[Trouble " + number + "]";
    }
}
  • ๋ฐœ์ƒํ•œ ํŠธ๋Ÿฌ๋ธ”์„ ํ‘œํ˜„ํ•˜๋Š” ํด๋ž˜์Šค์ด๋‹ค.

Supportย ํด๋ž˜์Šค

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public abstract class Support {
	private String name;
    private Support next;
    
    public Support(String name) {
    	this.name = name;
        this.next = null;
    }
    
    public Support setNext(Support next) {
    	this.next = next;
        return next;
    }
    
    public void support(Trouble trouble) {
    	if (resolve(trouble)) {
        	done(trouble);
        } else if (next != null) {
        	next.support(trouble);
        } else {
        	fail(trouble);
        }
    }
    
    @Override
    public String toString() {
    	return "[" + name + "]";
    }
    
	protected abstract boolean resolve(Trouble trouble);
    
    protected void done(Trouble trouble) {
    	System.out.println(trouble + " is resolved by " + this + ".");
    }
    
    protected void fail(Trouble trouble) {
    	System.out.println(trouble + " cannot be resolved.");
    }
}	
  • ๋ฌธ์ œ ํ•ด๊ฒฐ ์‚ฌ์Šฌ์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ ์ถ”์ƒ ํด๋ž˜์Šค์ด๋‹ค.
  • resolveย ๋ฉ”์†Œ๋“œ๋Š” ํ•˜์œ„ ํด๋ž˜์Šค์—์„œ ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋Š” ์ถ”์ƒ ๋ฉ”์†Œ๋“œ์ด๋‹ค.

NoSupportย ํด๋ž˜์Šค

1
2
3
4
5
6
7
8
9
10
public class NoSupport extends Support {
	public NoSupport(String name) {
    	super(name);
    }
    
    @Override
    protected boolean resolve(Trouble trouble) {
    	return false;
    }
}
  • Supportย ํด๋ž˜์Šค์˜ ํ•˜์œ„ ํด๋ž˜์Šค๋กœ,ย resolveย ๋ฉ”์†Œ๋“œ๋Š” ํ•ญ์ƒย false๋ฅผ ๋ฐ˜ํ™˜ํ•˜์—ฌ ์–ด๋–ค ๋ฌธ์ œ๋„ ํ•ด๊ฒฐํ•˜์ง€ ์•Š๋Š” ํด๋ž˜์Šค์ด๋‹ค.

LimitSupportย ํด๋ž˜์Šค

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class LimitSupport extends Support {
	private int limit;
    
    public LimitSupport(String name, int limit) {
    	super(name);
        this.limit = limit;
    }
    
    @Override
    protected boolean resolve(Trouble trouble) {
    	if (trouble.getNumber() < limit) {
        	return true;
        } else {
        	return false;
        }
    }
}
  • Supportย ํด๋ž˜์Šค์˜ ํ•˜์œ„ ํด๋ž˜์Šค๋กœ,ย limitย ๋ฏธ๋งŒ์˜ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ํด๋ž˜์Šค์ด๋‹ค.
  • ๋ณธ ์˜ˆ์ œ ํ”„๋กœ๊ทธ๋žจ์€ย resolveย ๋ฉ”์†Œ๋“œ์—์„œย true๋ฅผ ๋ฐ˜ํ™˜ํ•  ๋ฟ์ด์ง€๋งŒ, ์‹ค์ œ๋กœ๋Š” ์ด๊ณณ์—์„œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

OddSupportย ํด๋ž˜์Šค

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class OddSupport extends Support {
	public OddSupport(String name) {
    	super(name);
    }
    
    @Override
    protected boolean resolve(Trouble trouble) {
    	if (trouble.getNumber() % 2 == 1) {
        	return true;
        } else {
        	return false;
        }
    }	
}
  • Supportย ํด๋ž˜์Šค์˜ ํ•˜์œ„ ํด๋ž˜์Šค๋กœ, ํ™€์ˆ˜ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•œ๋‹ค.

SpecialSupportย ํด๋ž˜์Šค

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class SpecialSupport extends Support {
	private int number;
    
    public SpecialSupport(String name, int number) {
    	super(name);
        this.number = number;
    }
    
    @Override
    protected boolean resolve(Trouble trouble) {
    	if (trouble.getNumber() == number) {
        	return true;
        } else {
        	return false;
        }
    }	
}
  • Supportย ํด๋ž˜์Šค์˜ ํ•˜์œ„ ํด๋ž˜์Šค๋กœ ์ง€์ •๋œ ๋ฒˆํ˜ธ์— ํ•œ ํ•ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ํด๋ž˜์Šค์ด๋‹ค.

Mainย ํด๋ž˜์Šค

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Main {
	public static void main(String[] args) {
    	Support alice = new NoSupport("Alice");
    	Support bob = new LimitSupport("Bob", 100);
    	Support charlie = new SpecialSupport("Charlie", 429);
    	Support diana = new LimitSupport("Diana", 200);
    	Support elmo = new OddSupport("Elmo");
    	Support fred = new LimitSupport("Fred", 300);
    }
    
    alice
    	.setNext(bob)
    	.setNext(charle)
        .setNext(diana)
        .setNext(elmo)
        .setNext(fred)
        
    for (int i = 0; i < 500; i += 33) {
    	alice.support(new Trouble(i));
    }
}
  • ๋‹น์—ฐํ•˜๊ฒŒ๋„ ์‹คํ–‰ ๊ฒฐ๊ณผ์—ย Alice๋Š” ์ถœ๋ ฅ๋˜์ง€ ์•Š๋Š”๋‹ค.
  • ๋ชจ๋“  ๋ฌธ์ œ๋ฅผ ๋‹ค๋ฅธ ์‚ฌ๋žŒ์—๊ฒŒ ๋– ๋„˜๊ธฐ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

Chain of Responsibilityย ํŒจํ„ด์˜ ๋“ฑ์žฅ์ธ๋ฌผ

Supportย ํด๋ž˜์Šค

  • ์š”๊ตฌ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šคย API๋ฅผ ์ •์˜ํ•˜๋Š” ์ฒ˜๋ฆฌ์žย Handlerย ์—ญํ• ์„ ํ•œ๋‹ค.

NoSupport,ย LimitSupport,ย OddSupport,ย SpecialSupportย ํด๋ž˜์Šค

  • ์š”๊ตฌ๋ฅผ ๊ตฌ์ฒด์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ตฌ์ฒด์ ์ธ ์ฒ˜๋ฆฌ์žย ConcreteHandlerย ์—ญํ• ์„ ํ•œ๋‹ค.

Mainย ํด๋ž˜์Šค

  • ์ฒซ ๋ฒˆ์งธ ๊ตฌ์ฒด์ ์ธ ์ฒ˜๋ฆฌ์ž์—๊ฒŒ ์š”๊ตฌ๋ฅผ ํ•˜๋Š” ์š”๊ตฌ์žย Clientย ์—ญํ• ์„ ํ•œ๋‹ค.

์ฑ…์—์„œ ์ œ์‹œํ•˜๋Š” ํžŒํŠธ

์š”๊ตฌ์ž์™€ ๊ตฌ์ฒด์ ์ธ ์ฒ˜๋ฆฌ์ž๋ฅผ ์œ ์—ฐํ•˜๊ฒŒ ์—ฐ๊ฒฐํ•œ๋‹ค.

  • ์š”๊ตฌ์ž๊ฐ€ ์ฒซ ๋ฒˆ์งธ ๊ตฌ์ฒด์ ์ธ ์ฒ˜๋ฆฌ์ž์—๊ฒŒ ์š”๊ตฌ๋งŒ ํ•˜๋ฉด, ๋‚˜๋จธ์ง€๋Š” ๊ทธ ์š”๊ตฌ๊ฐ€ ๋ฌธ์ œ ํ•ด๊ฒฐ ์‚ฌ์Šฌ์„ ํ˜๋Ÿฌ๋‹ค๋‹ˆ๋‹ค๊ฐ€ ์ ์ ˆํ•œ ๊ตฌ์ฒด์ ์ธ ์ฒ˜๋ฆฌ์ž์—๊ฒŒ ์ฒ˜๋ฆฌ๋œ๋‹ค.
  • ๋งŒ์•ฝ ์ด ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด โ€˜์ด ์š”๊ตฌ๋Š” ์ด ์‚ฌ๋žŒ์ด ์ฒ˜๋ฆฌํ•ด์•ผ ํ•œ๋‹คโ€™๋Š” ์ •๋ณด๋ฅผ ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ์ค‘์•™์ง‘๊ถŒ์ ์œผ๋กœ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ํ•œ๋‹ค.
  • ๋˜ํ•œ ๊ทธ๋Ÿฐ ์ •๋ณด๋ฅผ ์š”๊ตฌํ•˜๋Š” ์‚ฌ๋žŒ์ด ๊ฐ–๊ณ  ์žˆ๋Š” ๊ฒƒ์€ ๋ถ€ํ’ˆ์œผ๋กœ์„œ์˜ ๋…๋ฆฝ์„ฑ์ด ํ›ผ์†๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ ์ ˆ์น˜ ์•Š๋‹ค.

๋™์ ์œผ๋กœ ์‚ฌ์Šฌ ํ˜•ํƒœ๋ฅผ ๋ฐ”๊พผ๋‹ค.

  • ์˜ˆ์ œ ํ”„๋กœ๊ทธ๋žจ์—์„œ๋Š” ์ง€์›ํŒ€์€ ํ•ญ์ƒ ๊ณ ์ •๋œ ์ˆœ์„œ๋Œ€๋กœ ๋˜์–ด ์žˆ๋‹ค.
  • ๊ทธ๋Ÿฌ๋‚˜ ์š”๊ตฌ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ตฌ์ฒด์ ์ธ ์ฒ˜๋ฆฌ์ž ์—ญํ•  ๊ฐ์ฒด์˜ ๊ด€๊ณ„๊ฐ€ ๋™์ ์œผ๋กœ ๋ณ€ํ™”ํ•˜๋Š” ์ƒํ™ฉ๋„ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ๋‹ค.
  • GUIย ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์•ฑ ํ™”๋ฉด์ƒ์— ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ž์œ ๋กญ๊ฒŒ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋Š”๋ฐ, ์ด ๋•Œ ํ•ด๋‹น ํŒจํ„ด์ด ํšจ๊ณผ์ ์œผ๋กœ ์ž‘๋™ํ•œ๋‹ค.

์ž๊ธฐ ์ผ์— ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ๊ตฌ์ฒด์ ์ธ ์ฒ˜๋ฆฌ์ž ์—ญํ• ์€ ์ž์‹ ์ด ํ•  ์ˆ˜ ์žˆ๋Š” ์ผ์— ์ง‘์ค‘ํ•˜๊ณ , ์ด์™ธ์˜ ์ผ์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š” ์—†๋Š” ์ฝ”๋“œ๋ฅผ ์ž์‹ ์ด ์•ˆ๊ณ  ๊ฐˆ ํ•„์š”๊ฐ€ ์—†์–ด์ง„๋‹ค.
  • ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜์ง€ ๋ชป ํ•  ๊ฒฝ์šฐ, ๊ทธ์ € ๋‹ค๋ฅธ ๊ตฌ์ฒด์ ์ธ ์ฒ˜๋ฆฌ์ž์—๊ฒŒ ๋ฌธ์ œ๋ฅผ ๋„˜๊ธฐ๋ฉด ๋œ๋‹ค.
  • ํ•ด๋‹น ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ ๊ด€๋ฆฌ์ž ํ•œ ๋ช…์ด ๋ˆ„๊ฐ€ ์š”๊ตฌ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ง€ ๋ชจ๋‘ ๊ฒฐ์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ทจํ•œ๋‹ค.
  • ํ˜น์€ โ€˜A๊ฐ€ ์•ˆ๋˜๋ฉด B์—๊ฒŒ, ๊ทธ๋ž˜๋„ ์•ˆ๋˜๋ฉด C์—๊ฒŒโ€™ ์ด๋Ÿฐ ์‹์œผ๋กœ ์ผ์˜ ํ• ๋‹น๊นŒ์ง€ ๊ฐœ๊ฐœ์˜ ๊ตฌ์ฒด์ ์ธ ์ฒ˜๋ฆฌ์ž ์—ญํ• ์— ๋ถ€๋‹ด์‹œํ‚ค๋Š” ๋ฐฉ๋ฒ•์„ ์ทจํ•˜๊ฒŒ ๋œ๋‹ค.

๋– ๋„˜๊ธฐ๊ธฐ๋กœ ์ฒ˜๋ฆฌ๊ฐ€ ์ง€์—ฐ๋˜์ง€ ์•Š์„๊นŒ?

  • ์‹ค์ œ๋กœ ํ•ด๋‹น ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ˆ„๊ฐ€ ์š”๊ตฌ๋ฅผ ์ฒ˜๋ฆฌํ• ์ง€ ์ •ํ•ด์ ธ ์žˆ๋Š” ํ”„๋กœ๊ทธ๋žจ๊ณผ ๋น„๊ตํ•˜๋ฉด ์ฒ˜๋ฆฌ๊ฐ€ ์ง€์—ฐ๋˜๋Š” ๊ฒƒ์ด ๋งž๋‹ค.
  • ํ•˜์ง€๋งŒ ์ด๊ฒƒ์€ ๋ฌด์—‡์„ ์šฐ์„ ์œผ๋กœ ํ• ์ง€ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„ ๋ฌธ์ œ์ด๋‹ค.
  • ์š”๊ตฌ์™€ ์ฒ˜๋ฆฌ์ž์˜ ๊ด€๊ณ„๊ฐ€ ๊ณ ์ •์ ์ด๊ณ  ์ฒ˜๋ฆฌ์†๋„๊ฐ€ ๋งค์šฐ ์ค‘์š”ํ•œ ๊ฒฝ์šฐ์—๋Š” ํ•ด๋‹น ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ํšจ๊ณผ์ ์ผ ์ˆ˜ ์žˆ๋‹ค.
This post is licensed under CC BY 4.0 by the author.