E D R , A S I H C RSS

Programming With Interface

์ถœ์ฒ˜: Holub on Patterns by Allen Holub

์ฑ…์—์„œ๋Š” ๋งํ•œ๋‹ค. ๋งŽ์€ ๊ฐœ๋ฐœ์ž๋“ค์ด ์ธํ„ฐํŽ˜์ด์Šค ๋ณด๋‹ค๋Š” ์ƒ์†์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐœ๋ฐœํ•œ๋‹ค๊ณ ... ๊ทธ๋ ‡๋‹ค! ์‚ฌ์‹ค์ด๋‹ค. ๋‚˜๋„ ์—ฌ์ง€๊ป ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๋ฌด์žฅํ•œ ์ฝ”๋“œ๋ฅผ ๋ณด์ง€ ๋ชปํ–ˆ๋‹ค.
์–ธ์ œ๋‚˜ ๊ฐœ๋ฐœ์„ ํ•  ๋•Œ '์–ด๋ผ~ ๊ฐ™์€ ์ผ ํ•˜๋Š”๋ฐ? ์ด๊ฑฐ Base ํด๋ž˜์Šค ๋งŒ๋“ค์–ด์„œ ์œ„๋กœ ์˜ฌ๋ ค์•ผ ๊ฒ ๋Š”๋ฐ?' ์ผ๋ง์˜ ํ‹ˆ๋„ ์ฃผ์ง€ ์•Š๊ณ  ์‹คํ–‰ํ•œ๋‹ค. ๋‹คํ˜•์„ฑ์„ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. '์™€์šฐ~! ํ•œ๊ฒฐ ๊น”๋”ํ•ด ์กŒ๋Š”๊ฑธ?' ํ•˜์ง€๋งŒ ์˜ค์‚ฐ์ด์—ˆ๋‹ค. ์‹œ๊ฐ„์ด ์ง€๋‚˜์„œ ๋จผ๊ฐ€ ์ถ”๊ฐ€ํ•  ๋™์ž‘๋“ค์ด ์ƒ๊ฒผ๋‹ค. ์ด์ œ ๊ณ ์น˜๊ธฐ ์‹œ์ž‘ํ•œ๋‹ค. Base ํด๋ž˜์Šค ๋ถ€ํ„ฐ... ๊ณ ์น˜๊ณ  ๋‚˜๋‹ˆ ์ปดํŒŒ์ผ์ด ๋˜์ง€ ์•Š๋Š”๋‹ค. ์ฝ”๋“œ ์ˆ˜์ •์˜ ์—ฌํŒŒ๊ฐ€ ํ•˜์œ„ ํด๋ž˜์Šค๋“ค์—๊ฒŒ ๊นŒ์ง€ ๋ฏธ์นœ๋‹ค. ์ •๋ง ๋ฏธ์นœ๋‹ค. ์ด๋Ÿฐ ์ƒ์†์„ ํ†ตํ•œ ๊ณ„์ธต ๊ตฌ์กฐ๋Š” ์ƒ์œ„ ํด๋ž˜์Šค์™€ ํ•˜์œ„ ํด๋ž˜์Šค์˜ ๊ฒฐํ•ฉ๋„๋ฅผ ๋†’์—ฌ์ค€๋‹ค. ์ง€๋‚˜ ์น˜๊ฒŒ ํฌ๊ฒŒ..! ๋™๊ฐํ•˜์ง€ ์•Š๋Š”๊ฐ€? ํ•˜๋‚˜๋ฅผ ๊ณ ์ณค๋Š”๋ฐ ์ˆ˜์ •ํ•  ๊บผ๋ฆฌ๊ฐ€ ๋งˆ๊ตฌ ์Ÿ์•„์ง€๋Š” ์ƒํ™ฉ์„...
์ƒ์†์„ ์‚ฌ์šฉํ•˜๋Š” ์ƒํ™ฉ์„ ๊ตญํ•œ ์‹œ์ผœ์•ผ ํ•  ๊ฒƒ๊ฐ™๋‹ค. ์ƒ์œ„ ํด๋ž˜์Šค์˜ ๊ธฐ๋Šฅ์„ 100%๋กœ ์‚ฌ์šฉํ•˜๋ฉด์„œ ์ถ”๊ฐ€์ ์ธ ๊ธฐ๋Šฅ์„ ํ•„์š”๋กœ ํ•˜๋Š” ๊ฐ์ฒด๊ฐ€ ํ•„์š”ํ•  ๋•Œ! .. ์ด๋Ÿฐ ์ƒํ™ฉ์ผ ๋•Œ๋Š” ์ƒ์†์„ ์‚ฌ์šฉํ•ด๋„ ํ›„ํ’์ด ๋‘๋ ต์ง€ ์•Š์„ ๊ฒƒ ๊ฐ™๋‹ค. GoF์˜ ์ฑ…์ด๋‚˜ ๋‹ค๋ฅธ DP์˜ ์ฑ…๋“ค์€ ํ•ญ์ƒ ๋งํ•œ๋‹ค. ์ƒ์† ๋ณด๋‹ค๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด ๋‹คํ˜•์„ฑ์„ ์‚ฌ์šฉํ•˜๋ผ๊ณ ... ๊ทธ ์ด์œ ๋ฅผ ์ด์ œ์•ผ ์•Œ ๊ฒƒ๊ฐ™๋‹ค. ๋™๊ฐํ•˜์ง€ ์•Š๋Š”๊ฐ€? Base ํด๋ž˜์Šค๋ฅผ ์ˆ˜์ •ํ•  ๋•Œ๋งˆ๋‹ค ํ•˜์œ„ ํด๋ž˜์Šค๋ฅผ ์ˆ˜์ •ํ•ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•œ๋‹ค๋ฉด ๊ทธ๊ฑด ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด ๋‹คํ˜•์„ฑ์„ ์ง€์›ํ•˜๋Š”๊ฒŒ ๋” ๋‚ซ๋‹ค๋Š” ์‹ ํ˜ธ์ด๋‹ค. ๊ฐ์ฒด๋Š” ์–ธ์ œ๋‚˜ SRP (Single Responsiblity Principle)์„ ์ง€์ผœ์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•œ๋‹ค.

Holub์ด ์‚ฌ์šฉํ•˜๋Š” ์˜ˆ์ œ๋ฅผ ๋ณด์ž. ์ƒ์†์„ ์‚ฌ์šฉํ•ด Stack์„ ๊ตฌํ˜„ํ•œ๋‹ค.
class Stack extends ArrayList {

 private int topOfStack = 0;

 

 public void push(Object article) {

  add(topOfStack++, article);

 }

 

 public Object pop() {

  return remove(--topOfStack);

 }

 

 public void pushMany(Object[] articles) {

  for(int i=0; i<articles.length; ++i) 

   push(articles[i]);

 }

}

์™„๋ฒฝํ•œ Stack์ด๋‹ค. ํ•˜์ง€๋งŒ ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์šฐ๋ฆฌ๋Š” Stack ๊ฐ์ฒด๊ฐ€ ์–ด๋–ป๊ฒŒ ๋Œ์•„๊ฐˆ์ง€ ์˜ˆ์ธก ํ•  ์ˆ˜ ์—†๋‹ค.

Stack aStack = new Stack();

stack.push("1");

stack.push("2");

stack.clear(); // ??? ArrayList์˜ ๋ฉ”์†Œ๋“œ์ด๋‹ค...;;
์ž ๋ชจ๋“  ๊ฐ’์„ clear ๋ฅผ ์‚ฌ์šฉํ•ด ์‚ญ์ œํ–ˆ๋Š”๋ฐ topOfStack์˜ ๊ฐ’์€ ์—ฌ์ „ํžˆ 3์ผ ๊ฒƒ์ด๋‹ค. ์ž ์ƒ์†์„ ํ†ตํ•œ ๋ฌธ์ œ๋ฅผ ํ•˜๋‚˜ ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค. ์ƒ์†์„ ์‚ฌ์šฉํ•˜๋ฉด ์›์น˜ ์•Š๋Š” ์ƒ์œ„ ํด๋ž˜์Šค์˜ ๋ฉ”์†Œ๋“œ๊นŒ์ง€ ์ƒ์†ํ•  ์ˆ˜ ์žˆ๋‹ค ๋Š” ๊ฒƒ์ด๋‹ค.

์ƒ์œ„ ํด๋ž˜์Šค๊ฐ€ ๊ฐ€์ง€๋Š” ๋ฉ”์†Œ๋“œ๊ฐ€ ์ ๋‹ค๋ฉด ๋ชจ๋‘ ์˜ค๋ฒ„๋ผ์ด๋”ฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์ง€๋งŒ ๋งŒ์•ฝ ๊ท€์ฐฎ์„ ์ •๋„๋กœ ๋งŽ์€ ๋ฉ”์†Œ๋“œ๊ฐ€ ์žˆ๋‹ค๋ฉด ์˜ค๋žœ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆด ๊ฒƒ์ด๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋งŒ์•ฝ ์ƒ์œ„ ํด๋ž˜์Šค๊ฐ€ ์ˆ˜์ •๋œ๋‹ค๋ฉด ๋‹ค์‹œ ๊ทธ ์—ฌํŒŒ๊ฐ€ ํ•˜์œ„ ํด๋ž˜์Šค์—๊ฒŒ ์ „๋‹ฌ๋œ๋‹ค. ๋˜ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์œผ๋กœ ํ•จ์ˆ˜๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋”ฉํ•˜์—ฌ ์˜ˆ์™ธ๋ฅผ ๋˜์ง€๋„๋ก ๋งŒ๋“ค์–ด ์›์น˜์•Š๋Š” ํ˜ธ์ถœ์„ ๋ง‰์„ ์ˆ˜ ์žˆ์ง€๋‹ค. ํ•˜์ง€๋งŒ ์ด๋Š” ์ปดํŒŒ์ผ ํƒ€์ž„ ์—๋Ÿฌ๋ฅผ ๋Ÿฐํƒ€์ž„ ์—๋Ÿฌ๋กœ ๋ฐ”๊พธ๋Š” ๊ฒƒ์ด๋‹ค. ๊ทธ๋ฆฌ๊ณ  LSP (Liskov Sustitution Principle : "๊ธฐ๋ฐ˜ ํด๋ž˜์Šค๋Š” ํŒŒ์ƒํด๋ž˜์Šค๋กœ ๋Œ€์ฒด ๊ฐ€๋Šฅํ•ด์•ผ ํ•œ๋‹ค") ์›์น™์„ ์–ด๊ธฐ๊ฒŒ ๋œ๋‹ค. ๋‹น์—ฐํžˆ ArrayList๋ฅผ ์ƒ์†๋ฐ›์€ Stack์€ clear ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์˜ˆ์™ธ๋ฅผ ๋˜์ง€๋‹ค๋‹ˆ ๋ง์ด ๋˜๋Š”๊ฐ€?

Stack์„ ๊ตฌํ˜„ํ•˜๋Š” ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์€ ์ƒ์† ๋Œ€์‹  ์บก์Аํ™”๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค.
class Stack {

 private int topOfStack = 0;

 private ArrayList theData = new ArrayList();

 

 public void push(Object article){

  theData.add(topOfStack++, article);

 }

 

 public Object pop() {

  return theData.remove(--topOfStack);

 }

 

 public void pushMany(Object [] articles) {

  for(int i=0; i<articles.length; ++i)

   push(articles[i]);

 }

 

 public int size() {

  return return theData.size();

 }

}
์ž.. Stack๊ณผ ArrayList๊ฐ„์˜ ๊ฒฐํ•ฉ๋„๊ฐ€ ๋งŽ์ด ๋‚ฎ์•„ ์กŒ๋‹ค. ๊ตฌํ˜„ํ•˜์ง€ ์•Š์€ clear ๋”ฐ์œ„ ํ˜ธ์ถœ ๋˜์ง€๋„ ์•Š๋Š”๋‹ค. ์™ ์ง€ ํ•ฉ์„ฑ์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ๋” ๋‚˜์€ ๊ฒƒ ๊ฐ™๋‹ค. ์ด๋Ÿฐ ๋ง๋„ ์žˆ๋‹ค. ์ƒ์† ๋ณด๋‹ค๋Š” ํ•ฉ์„ฑ์„ ์‚ฌ์šฉํ•˜๋ผ๊ณ ... ์ž ๋‹ค์‹œ ๋ณธ๋ก ์œผ๋กœ ๋“ค์–ด์™€ ์ € Stack์„ ์ƒ์†ํ•˜๋Š” ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด ๋ณด์ž. MonitorableStack์€ Stack์˜ ์ตœ์†Œ, ์ตœ๋Œ€ ํฌ๊ธฐ๋ฅผ ๊ธฐ์–ตํ•˜๋Š” Stack์ด๋‹ค.
class MonitorableStack extends Stack {

 private int maxHeight = 0;

 private int minHeight = 0;

 

 public void push(Object o) { 

  push(0);

  if(size() > maxHeight)

   maxHeight = size();

 }

 

 public Object pop() {

  Object poppedItem = pop();

  if(size() < minHeight)

   minHeight = size();

  return poppedItem;

 }

 

 public int maximumSize() { return maxHeight; }

 public int minimumSize() { return minHeight; }

}
๊น”๋”ํ•œ ์ฝ”๋“œ๊ฐ€ ๋‚˜์™”๋‹ค. ํ•˜์ง€๋งŒ MonitorableStack์€ pushMany ํ•จ์ˆ˜๋ฅผ ์ƒ์†ํ•œ๋‹ค. MonitorableStack์„ ์‚ฌ์šฉํ•ด pushMany ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด MonitorableStack์˜ ์ž…๋ ฅ ๋ฐ›์€ articles์˜ articles.length ๋งŒํผ push๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค. ํ•˜์ง€๋งŒ ์ง€๊ธˆ ํ˜ธ์ถœ๋œ push ๋ฉ”์†Œ๋“œ๋Š” MonitorableStack์˜ ๊ฒƒ์ด๋ผ๋Š” ์ ! ๋งค๋ฒˆ size() ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด ์ตœ๋Œ€ ํฌ๊ธฐ๋ฅผ ๊ฐฑ์‹ ํ•œ๋‹ค. ์†๋„๊ฐ€ ๋А๋ ค์งˆ ์ˆ˜๋„ ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋งŒ์•ฝ ๋ˆ„๊ตฐ๊ฐ€ Stack์˜ ์ฝ”๋“œ๋ฅผ ๋ณด๊ณ  pushMany ํ•จ์ˆ˜์˜ ๋น„ ํšจ์œจ์„ฑ ๋•Œ๋ฌธ์— Stack์„ ๋ฐ‘์˜ ์ฝ”๋“œ์™€ ๊ฐ™์ด ์ˆ˜์ •ํ–ˆ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ๋  ๊ฒƒ์ธ๊ฐ€???
class Stack {

 private int topOfStack = -1;

 private Object[] theData = new Object[1000]; 

 public void push(Object article) {

  theData[++topOfStack] = article;

 }

 

 public Object pop() {

  Object popped = theData[topOfStack--];

  theData[topOfStack] = null;

  return popped; 

 }

 

 public void pushMany(Object [] articles) {

  assert((topOfStack + articles.length) < theData.length);

  System.arraycopy(articles, 0, theData, topOfStack + 1, articles.length);

  topOfStack += articles.length;

 }

 

 public int size() {

  return topOfStack + 1;

 }

}
์™€!~ ์˜ˆ์ „์˜ Stack๋ณด๋‹ค ์„ฑ๋Šฅ์€ ํ™•์‹คํžˆ ์ข‹์•„ ์กŒ์„ ๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค. ๋”์ด์ƒ pushMany ๋ฉ”์†Œ๋“œ์—์„œ push ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š๋Š”๋‹ค. ์ด๋ ‡๊ฒŒ ๋˜๋ฉด MonitorableStack์€ ๋”์ด์ƒ Stack์˜ ์ตœ๋Œ€ ํฌ๊ธฐ๋ฅผ ์ถ”์ ํ•˜์ง€ ๋ชปํ•˜๊ฒŒ ๋œ๋‹ค. ์˜ˆ๊ธฐ์น˜ ์•Š์€ ๊ฒฐ๊ณผ์ด๋‹ค. ์ƒ์†์„ ์‚ฌ์šฉํ•œ ๊ตฌํ˜„์œผ๋กœ ๋ฐœ์ƒํ•œ ๋ฌธ์ œ์ด๋‹ค. ์—ฌ๊ธฐ๊นŒ์ง€ ๊ธ€์„ (์ฑ…์˜ ๋‚ด์šฉ) ์ฝ์—ˆ๋‹ค๋ฉด, ์•„๋งˆ '์ƒ์†์„ ์‚ฌ์šฉํ•˜๊ธฐ ์ „์— ํ•œ๋ฒˆ ๋” ์ƒ๊ฐํ•˜๋Š”๊ฒŒ ์ข‹๊ฒ ๋‹ค' ๋ผ๋Š” ์ƒ๊ฐ์„ ๊ฐ€์Šด ๊นŠ์ด ๋А๊ผˆ์„ ๊ฒƒ์ด๋‹ค. ์•„๋‹ˆ๋ฉด ๋ณ„์ˆ˜ ์—†๋Š” ์ผ์ด๋‹ค... :(

์ž ๊ธธ์—ˆ๋˜ ์—ฌํ–‰์˜ ์ข…์ฐฉ์ ์ด๋‹ค. ์ตœ์ข… ์ฝ”๋“œ๋ฅผ ๋ณด์ž. ์œ„์—์„œ ๋งํ–ˆ๋˜ ์ƒ์†๋ณด๋‹ค๋Š” ํ•ฉ์„ฑ์„... ์ƒ์†๋ณด๋‹ค๋Š” ์ธํ„ฐํŽ˜์ด๋ฅผ... ์ด๋ž€ ๋ง์„ ์ข…ํ•ฉ ํ•˜๋ฉด ...

"์œ„์ž„(ํ•ฉ์„ฑ)์„ ํ†ตํ•ด ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜์ž." ๋ผ๋Š” ๊ฒฐ๋ก ์ด ๋‚˜์˜จ๋‹ค.


interface Stack {

 void push(Object article);

 Object pop();

 void pushMany(Object [] articles);

 int size();

}

 

class SimpleStack implements Stack {

 private int topOfStack = 0;

 private ArrayList theData = new ArrayList();

 

 public void push(Object article){

  theData.add(topOfStack++, article);

 }

 

 public Object pop() {

  return theData.remove(--topOfStack);

 }

 

 public void pushMany(Object [] articles) {

  for(int i=0; i<articles.length; ++i)

   push(articles[i]);

 }

 

 public int size() {

  return return theData.size();

 } 

}

 

class MonitorableStack implements Stack {

 private int maxHeight = 0;

 private int minHeight = 0;

 private SimpleStack stack = new SimpleStack(); 

 

 public void push(Object o) { 

  stack.push(0);

  if(stack.size() > maxHeight)

   maxHeight = size();

 }

 

 public Object pop() {

  Object poppedItem = stack.pop();

  if(size() < minHeight)

   minHeight = stack.size();

  return poppedItem;

 }

 

 public void pushMany(Object [] articles) {

  for(int i=0; i<articles.length; ++i)  

   push(articles[i]);

 

  if(stack.size() > maxHeight)

   maxHeight = stack.size();  

 }

 

 public int maximumSize() { return maxHeight; }

 public int minimumSize() { return minHeight; } 

 public int size() { stack.size(); }

}
์™„์„ฑ๋œ ์ฝ”๋“œ์—์„œ๋Š” ์ƒ์†์œผ๋กœ ์ธํ•œ ๋ฌธ์ œ๋“ค์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค.
Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2021-02-07 05:24:03
Processing time 0.0248 sec