๋ณธ๋ฌธ์œผ๋กœ ๊ฑด๋„ˆ๋›ฐ๊ธฐ

๐ŸŒˆ Chapter 2: Education

๐Ÿฆ„ ๊ฐ€๋Šฅํ•˜๋‹ค๋ฉด ์ ๊ฒŒ ์บก์Šํ™”ํ•˜์„ธ์š”โ€‹

  • ๋ณต์žก์„ฑ์ด ๋†’์„์ˆ˜๋ก ์œ ์ง€๋ณด์ˆ˜์„ฑ์ด ์ €ํ•˜๋˜๊ณ , ์‹œ๊ฐ„๊ณผ ๋ˆ์ด ๋‚ญ๋น„๋˜๋ฉฐ, ๊ณ ๊ฐ ๋งŒ์กฑ๋„๊ฐ€ ๋–จ์–ด์ง„๋‹ค. ๋•Œ๋ฌธ์— 4๊ฐœ ๋˜๋Š” ๊ทธ ์ดํ•˜์˜ ๊ฐ์ฒด๋ฅผ ์บก์Šํ™”ํ•  ๊ฒƒ์„ ๊ถŒ์žฅํ•œ๋‹ค.
  • ๋‚ด๋ถ€์— ์บก์Šํ™”๋œ ๊ฐ์ฒด ์ „์ฒด๋ฅผ ๊ฐ€๋ฆฌ์ผœ ๊ฐ์ฒด์˜ ์ƒํƒœ ๋˜๋Š” ์‹๋ณ„์ž๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.
class Cash {
// 3๊ฐœ์˜ ๊ฐ์ฒด๋ฅผ ์บก์Šํ™”ํ•˜๊ณ  ์žˆ๋‹ค.
private Integer digits;
private Integer cents;
private String currency;
}
  • ๋™์ผํ•œ ๊ฐ’์˜ ๋‹ฌ๋Ÿฌ, ์„ผํŠธ, ํ†ตํ™”๋ฅผ ์บก์Šํ™”ํ•˜๋Š” Cash ํด๋ž˜์Šค์˜ ๋‘ ๊ฐ์ฒด๋Š” ์„œ๋กœ ๋™์ผํ•˜๋‹ค๋Š” ๋œป์ด๋‹ค.
Cash x = new Cash(29, 95, "USD");
Cash y = new Cash(29, 95, "USD");

assert x.equals(y);
assert x == y;
  • ์œ„ ์˜ˆ์ œ๋Š” ๋‘ ๊ฐ์ฒด x์™€ y์˜ ์ƒํƒœ๋Š” ๋™์ผํ•˜์ง€๋งŒ ์‹๋ณ„์ž๋Š” ์„œ๋กœ ๋‹ค๋ฅด๋‹ค. ==์—ฐ์‚ฐ์ž์™€ equals๋กœ ๋‘ ๊ฐ์ฒด๊ฐ€ ์„œ๋กœ ๋™์ผํ•˜์ง€ ์•Š๋‹ค๊ณ  ํŒ๋‹จํ•œ๋‹ค.
  • Java๋ฅผ ๋น„๋กฏํ•œ OOP ์–ธ์–ด์—์„œ ๊ฐ์ฒด๋Š” ๋‹จ์ง€ ๋ฉ”์„œ๋“œ๊ฐ€ ์ถ”๊ฐ€๋œ ๋ฐ์ดํ„ฐ์˜ ์ง‘ํ•ฉ์ผ ๋ฟ์ด๋‹ค. ๋ฐ์ดํ„ฐ์˜ ์ €์žฅ ์—ฌ๋ถ€์™€ ์ƒ๊ด€์—†์ด ๋ณต์‚ฌ๋ณธ์„ ๋น„๊ตํ•˜๋Š” ๊ฒฝ์šฐ์—๋„ ๋‹ค๋ฅด๋‹ค.
Object x = new Object();
Object y = new Object();

assert x.equals(y); // ์‹คํŒจ
  • ๋‚ด๋ถ€์— ์บก์Šํ™”๋œ ๋ชจ๋“  ๊ฐ์ฒด๋“ค์ด ๊ฐ์ฒด์˜ ์‹๋ณ„์ž๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ์š”์†Œ๋ผ๋Š” ์‚ฌ์‹ค์— ๋™์˜ํ•œ๋‹ค๋ฉด, ์ด์ œ ์บก์Šํ™”ํ•˜๊ธฐ์— ์ ํ•ฉํ•œ ๊ฐ์ฒด์˜ ์ˆ˜๋ฅผ ๊ฒฐ์ •ํ•ด์•ผ ํ•œ๋‹ค.
  • ์ตœ๋Œ€ 4๊ฐœ๊ฐ€ ํ•ฉ๋ฆฌ์ ์ธ ์ด์œ ๋Š” 4๊ฐœ ์ด์ƒ์˜ ์žํ‘œ๋Š” ์ง๊ด€์— ์œ„๋ฐฐ๋œ๋‹ค๋Š” ์‚ฌ์‹ค์ด๋‹ค.(์‚ฌ๋žŒ์€ ์ด๋ฆ„, ์ƒ๋…„์›”์ผ / ์ž๋™์ฐจ๋Š” ์ œ์กฐ์‚ฌ, ๋ชจ๋ธ, ์ œ์กฐ๋…„๋„)
  • ๋” ๋งŽ์€ ๊ฐ์ฒด๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋ฉด, ํด๋ž˜์Šค๋ฅผ ๋” ์ž‘์€ ํด๋ž˜์Šค๋“ค๋กœ ๋ถ„ํ•ดํ•ด์•ผ ํ•œ๋‹ค.

๐Ÿฆ„ ์ตœ์†Œํ•œ ๋ญ”๊ฐ€๋Š” ์บก์Šํ™”ํ•˜์„ธ์š”โ€‹

  • ๋‹ค์Œ ์˜ˆ๋Š” ์บก์Šํ™”๋ฅผ ํ•˜์ง€ ์•Š์€ ๊ฐ์ฒด์ด๋‹ค.
class Year {
int read() {
return System.currentTimeMillis()
/ (1000 * 60 * 60 * 24 * 30 * 12) - 1970;
}
}
  • ํ”„๋กœํผํ‹ฐ๊ฐ€ ์—†๋Š” ํด๋ž˜์Šค๋Š” ๊ฐ์ฒด์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ์ •์  ๋ฉ”์„œ๋“œ์™€ ์œ ์‚ฌํ•˜๋‹ค. ์ด๋Ÿฐ ํด๋ž˜์Šค๋Š” ์•„๋ฌด๋Ÿฐ ์ƒํƒœ์™€ ์‹๋ณ„์ž๋„ ๊ฐ€์ง€์ง€ ์•Š๊ณ  ์˜ค์ง ํ–‰๋™๋งŒ์„ ํฌํ•จํ•œ๋‹ค.
  • ์‹คํ–‰์œผ๋กœ๋ถ€ํ„ฐ ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ์„ ๊ณ ๋ฆฝ์‹œ์ผœ์•ผ ํ•œ๋‹ค. ๋‹ค์‹œ ๋งํ•ด์„œ ์˜ค์ง constructor์—์„œ๋งŒ new์—ฐ์‚ฐ์ž๋ฅผ ํ—ˆ์šฉํ•ด์•ผ ํ•œ๋‹ค๋Š” ๋œป์ด๋‹ค.
class Year {
private Millis millis;

Year(Millis msec) {
this.millis = msec;
}

int read() {
return this.millis.read()
/ (1000 * 60 * 60 * 24 * 30 * 12) - 1970;
}
}
  • ๊ฐ์ฒด๋Š” ๋ฌด์–ธ๊ฐ€๋ฅผ ์บก์Šํ™”ํ•ด์•ผ ํ•œ๋‹ค. ์ด ๊ฐ์ฒด๋Š” ์ž๊ธฐ ์ž์‹ ์„ ์‹๋ณ„ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋‹ค๋ฅธ ๊ฐ์ฒด๋“ค์„ ์บก์Šํ™”ํ•ด์•ผ ํ•œ๋‹ค.
  • ๋งŒ์•ฝ ๊ฐ์ฒด๊ฐ€ ์–ด๋–ค ๊ฒƒ๋„ ์บก์Šํ™”ํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ๊ฐ์ฒด์˜ ์ขŒํ‘œ๋Š” ๊ฐ์ฒด ์ž์‹ ์ด ์„ธ๊ณ„ ์ „์ฒด๊ฐ€ ๋˜์–ด์•ผ ํ•œ๋‹ค.
class Universe {

}
  • ์˜ค์ง ํ•˜๋‚˜์˜ ์„ธ๊ณ„๋งŒ ์กด์žฌํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด ํด๋ž˜์Šค๋Š” ์˜ค์ง ํ•˜๋‚˜๋งŒ ์กด์žฌํ•ด์•ผ ํ•œ๋‹ค.
  • ๋‹ค์Œ ์˜ˆ์ œ๋Š” ์™„๋ฒฝํ•œ ๊ฐ์ฒด์ง€ํ–ฅ ์„ค๊ณ„๋ฅผ ์ ์šฉํ•œ ๋ชจ์Šต์ด๋‹ค.
class Year {
private Number num;

Year(final Millis msec) {
this.num = new Min(
new Div(
msec,
new Mul(1000, 60, 60, 24, 30, 12)
),
1970
);
}

int read() {
return this.num.intValue();
}
}
  • ๋˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.
class Year {
private Number num;

Year(final Millis msec) {
this.num = msec.div(
1000.mul(60).mul(60).mul(24).mul(30).mul(12)
).min(1970);
}

int read() {
return this.num.intValue();
}
}

๐Ÿฆ„ ํ•ญ์ƒ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.โ€‹

  • ๊ฐ์ฒด๋“ค์€ ์„œ๋กœ๋ฅผ ํ•„์š”๋กœ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฒฐํ•ฉ๋œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.
  • ์„ค๊ณ„๋ฅผ ์‹œ์ž‘ํ•˜๋Š” ๋‹จ๊ณ„์—์„œ ๊ฐ๊ฐ์˜ ๊ฐ์ฒด๊ฐ€ ์–ด๋–ค ์ผ์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜๊ณ  ๋‹ค๋ฅธ ๊ฐ์ฒด์—๊ฒŒ ์–ด๋–ค ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•˜๋Š” ์ง€๋ฅผ ์ •ํ™•ํ•˜๊ณ  ์•Œ๊ณ  ์žˆ๋Š” ํŽธ์ด ๋‚ซ๊ธฐ ๋•Œ๋ฌธ์— ๊ฒฐํ•ฉ์€ ์œ ์šฉํ•˜์ง€๋งŒ ๊ฐ์ฒด์˜ ์ˆ˜๊ฐ€ ์ˆ˜์‹ญ ๊ฐœ๋ฅผ ๋„˜๊ฑฐ๊ฐ€๋ฉด์„œ๋ถ€ํ„ฐ ๊ฐ์ฒด ์‚ฌ์ด์˜ ๊ฐ•ํ•œ ๊ฒฐํ•ฉ๋„์˜ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋œ๋‹ค.
  • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „์ฒด๋ฅผ ์œ ์ง€๋ณด์ˆ˜ ๊ฐ€๋Šฅํ•˜๋„๋ก ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด์„œ๋Š” ๊ฐ์ฒด๋ฅผ ๋ถ„๋ฆฌํ•ด์•ผํ•œ๋‹ค.
  • ๊ฐ์ฒด ๋ถ„๋ฆฌ๋ž€ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ๋‹ค๋ฅธ ๊ฐ์ฒด๋ฅผ ์ˆ˜์ •ํ•˜์ง€ ์•Š๊ณ ๋„ ํ•ด๋‹น ๊ฐ์ฒด๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“ ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค. ์ด๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๋Š” ๋„๊ตฌ๊ฐ€ ๋ฐ”๋กœ ์ธํ„ฐํŽ˜์ด์Šค์ด๋‹ค.
interface Cash {
Cash multiply(float factor);
}
  • Cash๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๊ฐ์ฒด๊ฐ€ ๋‹ค๋ฅธ ๊ฐ์ฒด์™€ ์˜์‚ฌ์†Œํ†ตํ•˜๊ธฐ ์œ„ํ•ด ๋”ฐ๋ผ์•ผํ•˜๋Š” ๊ณ„์•ฝ์ด๋‹ค.
class DefaultCash implements Cash {
private int dollars;

DefaultCash(int dlr) {
this.dollars = dlr;
}

// ๊ณ„์•ฝ์— ์˜์กด
@Override
Cash multiply(float factor) {
return new DefaultCash(this.dollars * factor);
}
}
  • ๊ธˆ์•ก์ด ํ•„์š”ํ•˜๋‹ค๋ฉด ์‹ค์ œ ๊ตฌํ˜„ ๋Œ€์‹  ๊ณ„์•ฝ์— ์˜์กดํ•˜๋ฉด ๋œ๋‹ค.
class Employee {
private Cash salary;
}
  • Employee ํด๋ž˜์Šค๋Š” Cash ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ตฌํ˜„ ๋ฐฉ๋ฒ•์— ์•„๋ฌด๋Ÿฐ ๊ด€์‹ฌ์ด ์—†๋‹ค. ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š” ์ง€๋„ ๊ด€์‹ฌ์—†๋‹ค. ๋•Œ๋ฌธ์— ๋Š์Šจํ•˜๊ฒŒ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ถ”๊ฐ€๋กœ ํด๋ž˜์Šค ์•ˆ์˜ ๋ชจ๋“  ํผ๋ธ”๋ฆญ ๋ฉ”์„œ๋“œ๊ฐ€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋„๋ก ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค. ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์„ค๊ณ„๋œ ํด๋ž˜์Šค๋ผ๋ฉด ์ตœ์†Œํ•œ ํ•˜๋‚˜์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ผ๋„ ๊ตฌํ˜„ํ•˜์ง€ ์•Š๋Š” ํผ๋ธ”๋ฆญ ๋ฉ”์„œ๋“œ๋ฅผ ํฌํ•จํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค.
  • ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ค๊ณ„ํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค.
class Cash {
public int cents() {
// ์–ด๋–ค ์ž‘์—…์„ ์ˆ˜ํ–‰
}
}
  • cents ๋ฉ”์„œ๋“œ๋Š” ์–ด๋–ค ๊ฒƒ๋„ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค. ์ด ์„ค๊ณ„๋Š” ํด๋ž˜์Šค์˜ ์‚ฌ์šฉ์ž๋กœ ํ•˜์—ฌ๊ธˆ ์ด ํด๋ž˜์Šค์— ๊ฐ•ํ•˜๊ฒŒ ๊ฒฐํ•ฉ๋˜๋„๋ก ์กฐ์žฅํ•œ๋‹ค. ๋‹ค๋ฅธ ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๊ฐ€ ์ง์ ‘์ ์œผ๋กœ Cash.cents()๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ๋ฐ–์— ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ƒˆ๋กœ์šด ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•ด์„œ ๊ตฌํ˜„์„ ๋Œ€์ฒดํ•  ์ˆ˜ ์—†๋‹ค.
  • ํด๋ž˜์Šค๊ฐ€ ์กด์žฌํ•˜๋Š” ์ด์œ ๋Š” ๋‹ค๋ฅธ ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ํด๋ž˜์Šค์˜ ์„œ๋น„์Šค๋ฅผ ํ•„์š”๋กœ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๊ณ , ์„œ๋น„์Šค๋Š” ๊ณ„์•ฝ์ด์ž ์ธํ„ฐํŽ˜์ด์Šค์ด๊ธฐ ๋•Œ๋ฌธ์— ํด๋ž˜์Šค๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์„œ๋น„์Šค๋Š” ์–ด๋”˜๊ฐ€์— ๋ฌธ์„œํ™”๋˜์–ด์•ผ ํ•œ๋‹ค.
  • ๋™์ผํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ์—ฌ๋Ÿฌ ํด๋ž˜์Šค๋“ค์ด ์กด์žฌํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ฐ๊ฐ์˜ ๊ฒฝ์Ÿ์ž๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ๊ฒฝ์Ÿ์ž๋ฅผ ์‰ฝ๊ฒŒ ๋Œ€์ฒดํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค. ์ด๊ฒƒ์ด ๋Š์Šจํ•œ ๊ฒฐํ•ฉ๋„์˜ ์˜๋ฏธ์ด๋‹ค.

๐Ÿฆ„ ๋ฉ”์„œ๋“œ ์ด๋ฆ„์„ ์‹ ์ค‘ํ•˜๊ฒŒ ์„ ํƒํ•˜์„ธ์š”โ€‹

  • ๊ฐ„๋‹จํ•œ ๋ฒ•์น™์€ ๋นŒ๋”(builder)์˜ ์ด๋ฆ„์€ ๋ช…์‚ฌ๋กœ, ์กฐ์ •์ž(manipulator)์˜ ์ด๋ฆ„์€ ๋™์‚ฌ๋กœ ์ง“๋Š” ๊ฒƒ์ด๋‹ค.
  • ๋นŒ๋”๋ž€ ๋ญ”๊ฐ€๋ฅผ ๋งŒ๋“ค๊ณ  ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค. ๋นŒ๋”๋Š” ํ•ญ์ƒ ๋ญ”๊ฐ€๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•œ๋‹ค. ๋นŒ๋”์˜ ๋ฐ˜ํ™˜ํƒ€์ž…์€ ์ ˆ๋Œ€ void๊ฐ€ ๋  ์ˆ˜ ์—†์œผ๋ฉฐ, ์ด๋ฆ„์€ ํ•ญ์ƒ ๋ช…์‚ฌ์—ฌ์•ผ ํ•œ๋‹ค.
int pow(int base, int power);
float speed();
Employee employee(int id);
String parsedCell(int x, int y); // ํ˜•์šฉ์‚ฌ์ธ parsed๊ฐ€ ๋ช…์‚ฌ์ธ cell์„ ๊พธ๋ฏธ๊ณ  ์žˆ์„ ๋ฟ ๋ช…์‚ฌ๋‹ค.
  • ๊ฐ์ฒด๋กœ ์ถ”์ƒํ™”ํ•œ ์‹ค์„ธ๊ณ„ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์กฐ์ •์ž๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค. ์กฐ์ •์ž์˜ ๋ฐ˜ํ™˜ ํƒ€์ž…์€ ํ•ญ์ƒ void์ด๊ณ , ์ด๋ฆ„์€ ํ•ญ์ƒ ๋™์‚ฌ์ด๋‹ค.
void save(String content);
void put(String key, Float value);
void remove(Employee emp);
void quicklyPrint(int id); // ๋ถ€์‚ฌ์˜ ๊พธ๋ฐˆ์„ ๋ฐ›๋Š” ๋™์‚ฌ
  • ๋‹ค์Œ์€ ์›์น™์„ ์œ„๋ฐ˜ํ•˜๋Š” ์ž˜๋ชป๋œ ์˜ˆ
// ์ €์žฅ๋œ ์ „์ฒด ๋ฐ”์ดํŠธ๋ฅผ ๋ฐ˜ํ™˜
int save(String content); // void๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ๋ฐ”๊พธ๊ฑฐ๋‚˜ bytesSaved()์™€ ๊ฐ™์€ ์ด๋ฆ„์œผ๋กœ ๋ณ€๊ฒฝ
// map์ด ๋ณ€๊ฒฝ๋œ ๊ฒฝ์šฐ TRUE๋ฅผ ๋ฐ˜ํ™˜
boolean put(String key, Float value); // void๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ๋ณ€๊ฒฝํ•˜๊ฑฐ๋‚˜ putOperation์œผ๋กœ ๋ณ€๊ฒฝ
// speed๋ฅผ ์ €์žฅํ•œ ํ›„ ์ด์ „ ๊ฐ’์„ ๋ฐ˜ํ™˜
float speed(float val);

๐ŸŽˆ ๋นŒ๋”๋Š” ๋ช…์‚ฌ๋‹คโ€‹

  • ์–ด๋–ค ๊ฐ“์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ์˜ ์ด๋ฆ„์„ ๋™์‚ฌ๋กœ ์ง“๋Š” ๊ฒƒ์€ ์ž˜๋ชป์ด๋‹ค.
class Bakery {
Food cookBrownie();
Drink brewCupOfCoffee(String flavor);
}
  • ์œ„์˜ ๋‘ ๋ฉ”์„œ๋“œ๋Š” ๊ฐ์ฒด์˜ ๋ฉ”์„œ๋“œ๊ฐ€ ์•„๋‹ˆ๋ผ ํ”„๋กœ์‹œ์ €์ด๋‹ค.
  • ๋‘ ๋ฉ”์„œ๋“œ์˜ ์ด๋ฆ„์€ Bakery๋ฅผ ์ž๋ฆฝ์ ์ด๊ณ  ์ž์œจ์ ์ธ ๊ฐ์ฒด๋กœ ์กด์ค‘ํ•ด์„œ๋Š” ์•ˆ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ์ฒด์—๊ฒŒ ํ•  ์ผ์„ ์ผ์ผ์ด ๋ช…๋ นํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์†์‚ญ์ธ๋‹ค. ์ด๊ฒƒ์€ ๊ฐ์ฒด์ง€ํ–ฅ์ ์ธ ์ ‘๊ทผ๋ฐฉ๋ฒ•์ด ์•„๋‹ˆ๋ผ ์ ˆ์ฐจ์ ์ธ ์ ‘๊ทผ๋ฐฉ๋ฒ•์ด๋‹ค.
  • ๋ฉ”์„œ๋“œ์˜ ์ด๋ฆ„์„ ๋™์‚ฌ๋กœ ์ง€์„ ๋•Œ์—๋Š” ๊ฐ์ฒด์—๊ฒŒ ๋ฌด์—‡์„ ํ•  ์ง€๋ฅผ ์•Œ๋ ค์ฃผ์–ด์•ผ ํ•œ๋‹ค. ๋ฌด์—‡์„ ๋งŒ๋“ค์–ด์•ผ ํ•˜๋Š” ์ง€๋งŒ ์š”์ฒญํ•˜๊ณ , ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์€ ๊ฐ์ฒด ์Šค์Šค๋กœ ๊ฒฐ์ •ํ•˜๋„๋ก ํ•ด์•ผ ํ•œ๋‹ค.
// ์ž˜ ์ง€์–ด์ง„ ์˜ˆ
InputStream stream(URL url);
String content(File file);
int sum(int x, int y);

๐ŸŽˆ ์กฐ์ •์ž๋Š” ๋™์‚ฌ๋‹คโ€‹

  • ์‹ค์„ธ๊ณ„์˜ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์กฐ์ž‘ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š”, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ฐ์ฒด๊ฐ€ ๊ทธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋„๋ก ์š”์ฒญํ•œ๋‹ค.
class Pixel {
void paint(Color color);
}

Pixel center = new Pixel(50, 50);
center.paint(new Color("red"));
  • paint ๋ฉ”์„œ๋“œ๋Š” ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š๋Š”๋‹ค. ์š”์ฒญํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™๋‹ค.

๐ŸŽˆ ๋นŒ๋”์™€ ์กฐ์ •์ž ํ˜ผํ•ฉํ•˜๊ธฐโ€‹

  • ๋‹ค์Œ ์˜ˆ๋Š” ํŒŒ์ผ ๋‚ด์šฉ์„ ์ €์žฅํ•˜๊ณ  ์ €์žฅ๋œ ๋ฐ”์ดํŠธ ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ์ด๋‹ค.
class Document {
int write(InputStream content);
}
  • ์ด ๋ฉ”์„œ๋“œ๋Š” ์•ž์—์„œ ์„ค๋ช…ํ•œ ์›์น™์„ ์œ„๋ฐ˜ํ•˜๊ณ  ์žˆ๋‹ค. ์›์น™์ƒ์œผ๋กœ๋Š” ๋ฉ”์„œ๋“œ write์˜ ๋ฐ˜ํ™š ํƒ€์ž…์„ void๋กœ ๋ฐ”๊ฟ”์•ผ ํ•˜์ง€๋งŒ, ์‹ค์ œ๋กœ ์ €์žฅ๋œ ๋ฐ”์ดํŠธ ์ˆ˜๋ฅผ ์•Œ ํ•„์š”๊ฐ€ ์žˆ๋‹ค.
  • write() ๋ฉ”์„œ๋“œ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์“ฐ๋Š” ๋™์‹œ์—, ์“ฐ์—ฌ์ง„ ๋ฐ”์ดํŠธ ์ˆ˜๋ฅผ ์นด์šดํŠธํ•œ๋‹ค. ๋‹ค์‹œ ๋งํ•ด์„œ ํ•˜๋‚˜์˜ ๋ฉ”์„œ๋“œ ์•ˆ์—์„œ ๋„ˆ๋ฌด ๋ณต์žกํ•œ ์ผ์„ ์ฒ˜๋ฆฌํ•˜๊ณ  ์žˆ๋‹ค. ๋ฉ”์„œ๋“œ์˜ ๋ชฉ์ ์ด ๋ช…ํ™•ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๊น”๋”ํ•˜๊ฒŒ ๋ช…์‚ฌ๋‚˜ ๋™์‚ฌ ๋‘˜ ์ค‘ ํ•˜๋‚˜๋กœ ์ด๋ฆ„์„ ์ง€์„ ์ˆ˜๊ฐ€ ์—†๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ๋ฐฉ๋ฒ•์œผ๋กœ ๋ฆฌํŒฉํ† ๋ง์„ ํ•ด์•ผํ•œ๋‹ค.
class Document {
OutputPipe output(); // ๋นŒ๋”
}

class OutputPipe {
void write(InputStream content); // ์กฐ์ •์ž
int bytes(); // ๋นŒ๋”
long time(); // ๋นŒ๋”
}

๐ŸŽˆ Boolean ๊ฐ’์„ ๊ฒฐ๊ณผ๋กœ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒฝ์šฐโ€‹

  • Boolean ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ์˜ ์ด๋ฆ„์€ ์–ด๋–ป๊ฒŒ ์ง€์„๊นŒ?
  • Boolean ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋Š” ๊ทœ์น™์— ์žˆ์–ด์„œ ์˜ˆ์™ธ์ ์ธ ๊ฒฝ์šฐ์ด๋‹ค. ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด ๋ฉ”์„œ๋“œ๋“ค์€ ๋นŒ๋”์— ์†ํ•˜์ง€๋งŒ, ๊ฐ€๋…์„ฑ ์ธก๋ฉด์—์„œ ์ด๋ฆ„์„ ํ˜•์šฉ์‚ฌ๋กœ ์ง€์–ด์•ผ ํ•œ๋‹ค.
boolean empty(); // is empty
boolean readable(); // is readable
boolean negative(); // is negative
  • ์ ‘๋‘์‚ฌ is๋Š” ์ค‘๋ณต์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ฉ”์„œ๋“œ์˜ ์ด๋ฆ„์— ํฌํ•จ์‹œํ‚ค์ง€ ์•Š์ง€๋งŒ, ๋ฉ”์„œ๋“œ๋ฅผ ์ฝ์„ ๋•Œ๋Š” ์ผ์‹œ์ ์œผ๋กœ ์•ž์— ๋ถ™์—ฌ ์ž์—ฐ์Šค๋ฒŒ๊ฒŒ ๋“ค๋ฆฌ๋„๋ก ํ•ด์•ผ ํ•œ๋‹ค.
  • ์•„๋ž˜์˜ ๋ฉ”์„œ๋“œ์—์„œ๋Š” ๋ฌธ์ œ๊ฐ€ ๋  ์ˆ˜ ์žˆ๋Š”๋ฐ is๋ฅผ ๋ถ™์ด๋ฉด ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š์€ ๋ฌธ์žฅ์ด ๋งŒ๋“ค์–ด์ง€๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์ด๋Ÿฐ ๊ฒฝ์šฐ ๋” ์ ํ•ฉํ•œ ์ด๋ฆ„์€ equalTo์™€ present์ด๋‹ค.
boolean equals(Object obj);
boolean exists();
  • Boolean์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ํŠน๋ณ„ํ•˜๊ฒŒ ์ทจ๊ธ‰ํ•ด์•ผ ํ•˜๋Š” ์ด์œ ๋Š” Java๋ฅผ ํฌํ•จํ•œ ๋Œ€๋ถ€๋ถ„์˜ ์–ธ์–ด๋“ค์ด ๋…ผ๋ฆฌ ๊ตฌ์„ฑ์ž๋ฅผ ํŠน๋ณ„ํ•œ ๋ฐฉ์‹์œผ๋กœ ๋‹ค๋ฃจ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
  • ๋‹ค์Œ์€ ํด๋ž˜์Šค์— ๋ฌธ์ž์—ด์ด ๋น„์–ด์žˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” emptiness() ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•œ ํ›„ ์‚ฌ์šฉํ•œ ๊ฒƒ์ด๋‹ค.
if (name.emptiness() == true) {
// ๋ญ”๊ฐ€ ํ•œ๋‹ค.
}
  • ์ด ๋ฌธ์žฅ์€ if emptiness of the name is true๋กœ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ฝํžˆ์ง€๋งŒ Java์—์„œ๋Š” ์ด๋Ÿฐ ๋ฐฉ์‹์œผ๋กœ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์ง€ ์•Š๋Š”๋‹ค.
if (name.empty()) {
// ๋ญ”๊ฐ€ ํ•œ๋‹ค.
}
  • ์š”์•ฝํ•˜์ง€๋ฉด, ๋จผ์ € ๋ฉ”์„œ๋“œ์˜ ๋ชฉ์ ์ด ๋ฌด์—‡์ธ์ง€๋ฅผ ํ™•์ธํ•˜๊ณ , ๋ฉ”์„œ๋“œ๋Š” ๋นŒ๋”๋‚˜ ์กฐ์ •์ž, ๋‘˜ ์ค‘ ํ•˜๋‚˜์—ฌ์•ผ ํ•œ๋‹ค. ์ ˆ๋Œ€๋กœ ๋นŒ๋”์ธ ๋™์‹œ์— ์กฐ์ •์ž์ด๋ฉด ์•ˆ๋œ๋‹ค. ๋นŒ๋”๋Š” ๋ช…์‚ฌ๋กœ, ์กฐ์ •์ž๋Š” ๋™์‚ฌ๋กœ ์ง€์–ด์•ผ ํ•œ๋‹ค.

๐Ÿฆ„ ํผ๋ธ”๋ฆญ ์ƒ์ˆ˜(Public Constant)๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”โ€‹

  • ์ƒ์ˆ˜๋ผ๊ณ ๋„ ๋ถˆ๋ฆฌ๋Š” public static final ํ”„๋กœํผํ‹ฐ๋Š” ๊ฐ์ฒด ์‚ฌ์ด์— ๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด๋‹ค. ๊ธ€์ž ๊ทธ๋Œ€๋กœ ์ƒ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์•„์œ ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•˜๊ธฐ ์œ„ํ•ด์„œ์ด๋‹ค.
  • ํ•˜์ง€๋งŒ ๋ฐ˜๋Œ€ํ•˜๋Š” ์ด์œ  ๋˜ํ•œ ๊ฐ์ฒด๋“ค์€ ์–ด๋–ค ๊ฒƒ๋„ ๊ณต์œ ํ•ด์„œ๋Š” ์•ˆ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋Œ€์‹  ๋…๋ฆฝ์ ์ด์–ด์•ผํ•˜๊ณ  ๋‹ซํ˜€ ์žˆ์–ด์•ผ ํ•œ๋‹ค.
  • ์ƒ์ˆ˜๋ฅผ ์ด์šฉํ•œ ๊ณต์œ  ๋ฉ”์ปค๋‹ˆ์ฆ˜์€ ์บก์Šํ™”์™€ ๊ฐ์ฒด์ง€ํ–ฅ์ ์ธ ์‚ฌ๊ณ  ์ „์ฒด๋ฅผ ๋ถ€์ •ํ•˜๋Š” ์ผ์ด๋‹ค.
class Records {
private static final String EOL = "\r\n";

void write(Writer out) {
for (Record rec: this.all) {
out.write(rec.toString());
out.write(Records.EOL);
}
}
}
  • ์ด ์˜ˆ์ œ๋Š” Recodes ํด๋ž˜์Šค์˜ ๋‚ด๋ถ€์—์„œ๋งŒ ์‚ฌ์šฉ๋˜๋ฏ€๋กœ ์™„์ „ํžˆ ์šธ๋ฐ”๋ฅธ ์ƒํ™ฉ์ด๋‹ค. ํ•˜์ง€๋งŒ ๋‹ค๋ฅธ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” Rows ํด๋ž˜์Šค๊ฐ€ ์žˆ๋‹ค๋ฉด?
class Rows {
private static final String EOL = "\r\n";

void print(PrintStream pnt) {
for (Row row: this.fetch()) {
pnt.printf(
"{ %s }%s", row, Rows.EOL
);
}
}
}
  • Rows์˜ ๋กœ์ง์€ Records์˜ ๋กœ์ง๊ณผ ๋‹ค๋ฅด๋ฉฐ, ํ˜‘๋ ฅํ•˜๋Š” ๊ฐ์ฒด ์ง‘ํ•ฉ๋„ ์™„์ „ํžˆ ๋‹ค๋ฅด๋‹ค. ๋‘ ํด๋ž˜์Šค๋Š” ๊ณตํ†ต์ ์ด ์—†๋‹ค. ํ•˜์ง€๋งŒ ๋‘ ํด๋ž˜์Šค ๋ชจ๋‘ EOL private ์ƒ์ˆ˜๋ฅผ ์ •์˜ํ•˜๊ณ  ์žˆ๋‹ค. ๋•Œ๋ฌธ์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ค‘๋ณต ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด์•ผ ํ•œ๋‹ค.
public class Constants {
public static final String EOL = "\r\n";
}
  • ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด public์ด๋ผ ๋•Œ๋ฌธ์— ํด๋ž˜์Šค ๋กœ๋”์— ์˜ํ•ด ๋กœ๋”ฉ๋œ ๋ชจ๋“  ํด๋ž˜์Šค๋“ค์ด ์ƒ์ˆ˜์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค. ํผ๋ธ”๋ฆญ ์ƒ์ˆ˜๋ฅผ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ํ•˜์ง€๋งŒ ๊ฒฐํ•ฉ๋„๊ฐ€ ๋†’์•„์กŒ๊ณ  ์‘์ง‘๋„๊ฐ€ ๋‚ฎ์•„์กŒ๋‹ค.

๐ŸŽˆ ๊ฒฐํ•ฉ๋„ ์ฆ๊ฐ€โ€‹

  • ๋‹ค์Œ์€ Records ํด๋ž˜์Šค์™€ Rows ํด๋ž˜์Šค์ด๋‹ค.
class Records {
void write(Writer out) {
for (Record rec: this.all) {
out.write(rec.toString());
out.write(Constants.EOL); // here!
}
}
}

class Rows {
void print(PrintStream pnt) {
for (Row row: this.fetch()) {
pnt.printf(
"{ %s }%s", row, Constants.EOL // here!
);
}
}
}
  • ๋‘ ํด๋ž˜์Šค๋Š” ๋ชจ๋‘ ๊ฐ™์€ ๊ฐ์ฒด์— ์˜์กดํ•˜๊ณ  ์žˆ์œผ๋ฉฐ ์ด ์˜์กด์„ฑ์€ ํ•˜๋“œ ์ฝ”๋”ฉ๋˜์–ด ์žˆ๋‹ค.
  • Records.write(), Rows.print(), Constants,EOL ์„ธ ๊ณณ์—์„œ ์ฝ”๋“œ์˜ ์ผ๋ถ€๊ฐ€ ์„œ๋กœ ๊ฒฐํ•ฉ๋˜์–ด ์˜์กดํ•˜๊ณ  ์žˆ๋‹ค.

๐ŸŽˆ ์‘์ง‘๋„ ์ €ํ•˜โ€‹

  • ํผ๋ธ”๋ฆญ ์ƒ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ์ฒด์˜ ์‘์ง‘๋„๋Š” ๋‚ฎ์•„์ง„๋‹ค. ๋‚ฎ์€ ์‘์ง‘๋„๋Š” ๊ฐ์ฒด๊ฐ€ ์ž์‹ ์˜ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š”๋ฐ ๋œ ์ง‘์ค‘ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.
  • ์ƒ์ˆ˜๋Š” ์ž์‹ ์— ๊ด€ํ•ด ์•„๋ฌด ๊ฒƒ๋„ ์•Œ ์ง€ ๋ชปํ•˜๋ฉฐ, ์ž์‹ ์˜ ์กด์žฌ ์ด์œ ๋ฅผ ์ดํ•ดํ•˜์ง€ ๋ชปํ•˜๋Š” ํ•˜๋‚˜์˜ ํ…์ŠคํŠธ ๋ฉ์–ด๋ฆฌ์— ๋ถˆ๊ณผํ•˜๋‹ค.
  • ์˜๋ฏธ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” Records์™€ Rows ํด๋ž˜์Šค ์•ˆ์— ๋” ๋งŽ์€ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•œ๋‹ค. ๋ชฉ์ ์„ ๋ช…ํ™•ํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์ค„ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด์„œ ์ด ์›์‹œ์ ์ธ ์ •์  ์ƒ์ˆ˜๋ฅผ ๊ฐ์‹ธ์•ผ ํ•œ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋Ÿฐ ์ฝ”๋“œ๋Š” ์›๋ž˜ ์˜๋„ํ–ˆ๋˜ ๋ชฉ์ ๊ณผ ๋™๋–จ์–ด์ ธ ์žˆ์„ ์ˆ˜ ๋ฐ–์— ์—†๋‹ค.
  • ๋•Œ๋ฌธ์— ์ฝ”๋“œ ์ค‘๋ณต ๋ฌธ์ œ๋ฅผ ์ ์ ˆํ•˜๊ฒŒ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๊ฐ์ฒด ์‚ฌ์ด์— ๋ฐ์ดํ„ฐ๋ฅผ ์ค‘๋ณตํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค. ๋Œ€์‹ , ๊ธฐ๋Šฅ์„ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ƒˆ๋กœ์šด ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค.
// ๊ธฐ๋Šฅ์„ ๊ณตํ†ต์œผ๋กœ ์ œ๊ณตํ•œ ์ƒˆ๋กœ์šด ํด๋ž˜์Šค๋ฅผ ์ถ”๊ฐ€
class EOLString {
private final String origin;
EOLString(String src) {
this.origin = src;
}

@Override
String toString() {
return String.format("%S\r\n", origin);
}
}
  • ์ด์ œ ํ•„์š”ํ•œ ๊ณณ์—์„œ EOLString์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
class Records {
void write(Writer out) {
for (Record rec: this all) {
out.write(new EOLString(rec.toString()));
}
}
}

class Rows {
void print(PrintStream pnt) {
for (Row row: this.fetch()) {
pnt.printf(
new EOLString(
String.format("{ %s }", row)
)
);
}
}
}
  • ์ด์ œ ์ ‘๋ฏธ์‚ฌ๋ฅผ ์ค„ ๋งˆ์ง€๋ง‰์— ์ •ํ™•ํ•˜๊ฒŒ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๊ด€ํ•ด์„œ๋Š” EOLString์ด ์ฑ…์ž„์„ ์ง„๋‹ค.
  • EOLString์— ๋Œ€ํ•œ ๊ฒฐํ•ฉ์€ ๊ณ„์•ฝ์„ ํ†ตํ•ด ์ถ”๊ฐ€๋œ ๊ฒƒ์ด๋ฉฐ, ๊ณ„์•ฝ์— ์˜ํ•œ ๊ฒฐํ•ฉ์€ ์–ธ์ œ๋ผ๋„ ๋ถ„๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์œ ์ง€๋ณด์ˆ˜์„ฑ์œผ ์ €ํ•˜์‹œํ‚ค์ง€ ์•Š๋Š”๋‹ค.
  • ์š”์•ฝํ•˜์ž๋ฉด OOP์—์„œ ํผ๋ธ”๋ฆญ ์ƒ์ˆ˜๋ฅผ ์ ˆ๋Œ€๋กœ ์‚ฌ์šฉํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค. ์‚ฌ์†Œํ•ด ๋ณด์ด๋Š” ์ƒ์ˆ˜๋ผ๋„ ํ•ญ์ƒ ์ž‘์€ ํด๋ž˜์Šค๋ฅผ ์ด์˜ํ•ด์„œ ๋Œ€์ฒดํ•ด์•ผ ํ•œ๋‹ค.

๐Ÿฆ„ ๋ถˆ๋ณ€ ๊ฐ์ฒด๋กœ ๋งŒ๋“œ์„ธ์š”โ€‹

  • ๋ชจ๋“  ํด๋ž˜์Šค๋ฅผ ์ƒํƒœ ๋ณ€๊ฒฝ์ด ๋ถˆ๊ฐ€๋Šฅํ•œ ๋ถˆ๋ณ€ ํด๋ž˜์Šค(immutable class)๋กœ ๊ตฌํ˜„ํ•˜๋ฉด ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ํฌ๊ฒŒ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.
  • ๋ถˆ๋ณ€์„ฑ์€ ํฌ๊ธฐ๊ฐ€ ์ž‘๊ณ , ์‘์ง‘๋ ฅ์ด ๋†’์œผ๋ฉฐ, ๋Š์Šจํ•˜๊ฒŒ ๊ฒฐํ•ฉ๋˜๊ณ , ์œ ์ง€๋ณด์ˆ˜ํ•˜๊ธฐ ์‰ฌ์šด ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.
  • ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•œ ํ›„์— ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋Š” ๊ฐ์ฒด๋ฅผ ๋ถˆ๋ณ€ ๊ฐ์ฒด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.
  • ๋‹ค์Œ ์˜ˆ๋Š” ๊ฐ€๋ณ€ ๊ฐ์ฒด์ด๋‹ค.
class Cash {
private int dollars;

public void setDollars(int val) {
this.dollars = val;
}
}
  • ๋‹ค์Œ ์˜ˆ์ œ๋Š” ๋ถˆ๋ณ€ ๊ฐ์ฒด์ด๋‹ค.
class Cash {
private final int dollars;

Cash(int val) {
this.dollars = val;
}
}
  • final ํ‚ค์›Œ๋“œ๋Š” ์ƒ์„ฑ์ž ์™ธ๋ถ€์—์„œ ํ”„๋กœํผํ‹ฐ์˜ ๊ฐ’์„ ์ˆ˜์ •ํ•  ๊ฒฝ์šฐ ์ปดํŒŒ์ผ ํƒ€์ž„ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ด์•ผ ํ•œ๋‹ค๋Š” ์‚ฌ์‹ค์„ ์ปดํŒŒ์ผ๋Ÿฌ์—๊ฒŒ ์•Œ๋ ค์ค€๋‹ค.
  • ๋ถˆ๋ณ€ ๊ฐ์ฒด๋Š” ํ•„์š”ํ•œ ๋ชจ๋“  ๊ฒƒ์„ ๋‚ด๋ถ€์— ์บก์Šํ™”ํ•˜๊ณ  ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋„๋ก ํ†ต์ œํ•œ๋‹ค. ๋ถˆ๋ณ€ ๊ฐ์ฒด๋ฅผ ์ˆ˜์ •ํ•ด์•ผ ํ•œ๋‹ค๋ฉด ํ”„๋กœํผํ‹ฐ๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ๋Œ€์‹  ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ•œ๋‹ค.
  • ๋‹ค์Œ์€ ๊ฐ€๋ณ€ ํด๋ž˜์Šค๋กœ ๊ตฌํ˜„ํ•œ ์ฝ”๋“œ์ด๋‹ค.
class Cash {
private int dollars;

public void mul(int factor) {
this.dollars *= factor;
}
}
  • ๋‹ค์Œ์€ ๋™์ผํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ถˆ๋ณ€ ํด๋ž˜์Šค์ด๋‹ค.
class Cash {
private final int dollars;

public Cash mul(int factor) {
return new Cash(this.dollars * factor);
}
}
  • ๋ถˆ๋ณ€ ๊ฐ์ฒด๋Š” ์ž๊ธฐ ์ž์‹ ์„ ์ˆ˜์ •ํ•  ์ˆ˜ ์—†๊ณ  ํ•ญ์ƒ ์›ํ•˜๋Š” ์ƒํƒœ๋ฅผ ๊ฐ€์ง€๋Š” ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด์„œ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•œ๋‹ค.
  • ๋‹ค์Œ์€ ๊ฐ€๋ณ€ ๊ฐ์ฒด์˜ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•
Cash five = new Cash(5);
five.mul(10);
System.out.println(five); // 50
  • ๋‹ค์Œ์€ ๋ถˆ๋ณ€ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•œ ๋ฐฉ๋ฒ•์ด๋‹ค.
Cash five = new Cash(5);
Cash fifty = five.mul(10);
System.out.println(fifty); // 50
  • five ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๋‚˜๋ฉด five๋Š” fifty๊ฐ€ ๋  ์ˆ˜ ์—†๋‹ค. 5๋Š” 5์ผ ๋ฟ์ด๋‹ค.
  • ๊ฐ€๋ณ€ ๊ฐ์ฒด๋Š” ์—„๊ฒฉํ•˜๊ฒŒ ๊ธˆ์ง€ํ•ด์•ผ ํ•œ๋‹ค.

๐ŸŽˆ ์‹๋ณ„์ž ๊ฐ€๋ณ€์„ฑ(Identity Mutability)โ€‹

  • ๋ถˆ๋ณ€ ๊ฐ์ฒด์—๋Š” ์‹๋ณ„์ž ๊ฐ€๋ณ€์„ฑ ๋ฌธ์ œ๊ฐ€ ์—†๋‹ค. ์ด ๋ฌธ์ œ๋Š” ๋™์ผํ•ด ๋ณด์ด๋Š” ๋‘ ๊ฐ์ฒด๋ฅผ ๋น„๊ตํ•œ ํ›„ ํ•œ ๊ฐ์ฒด์˜ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•  ๋•Œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š”๋ฐ, ๋” ์ด์ƒ ๋™์ผํ•˜์ง€ ์•Š์ง€๋งŒ, ์—ฌ์ „ํžˆ ๋‘ ๊ฐ์ฒด๊ฐ€ ๋™์ผํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•œ๋‹ค. ๊ทธ ๋ฐ˜๋Œ€์ผ ์ˆ˜๋„ ์žˆ๋‹ค.
Map<Cash, String> map = new HashMap<>();
Cash five = new Cash("$5");
Cash ten = new Cash("$10");
map.put(five, "five");
map.put(ten, "ten");
five.mul(2);
System.out.println(map); // { $10 => "five", $10 => "ten" }
  • ์ด๋Ÿฌ๋ฉด map์€ ๋™์ผํ•œ ํ‚ค๊ฐ€ ๋‘ ๊ฐœ ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š๋‹ค. ์ฒ˜์Œ์—” ๋™์ผํ•˜์ง€ ์•Š์€ ๋‘ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ ๋’ค ๋‘ ๊ฐ์ฒด๋ฅผ map์— ์ถ”๊ฐ€ํ•˜๋Š”๋ฐ, ์ด๋•Œ๋Š” ํ‚ค๊ฐ€ ์„œ๋กœ ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— HashMap์€ ๋‘ ๊ฐœ์˜ ๋…๋ฆฝ์ ์ธ ์—”ํŠธ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ๊ทธ ํ›„ 5๋ฅผ 10์œผ๋กœ ๋ณ€๊ฒฝํ•ด๋„ map์—๊ฒŒ ์ด ์‚ฌ์‹ค์„ ์•Œ๋ ค์ฃผ์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— map์€ ๋ณ€๊ฒฝ์ด ์ผ์–ด๋‚ฌ๋‹ค๋Š” ์‚ฌ์‹ค์„ ์ „ํ˜€ ์ธ์‹ํ•˜์ง€ ๋ชปํ•œ๋‹ค.
  • ์ด ํ›„ ๋‘˜ ์ค‘ ํ•˜๋‚˜๋ฅผ ๊ฒ€์ƒ‰ํ•˜๋ ค๊ณ  ํ•˜๋ฉด, map ์ƒํƒœ๊ฐ€ ๋น„์ •์ƒ์ ์ด๊ธฐ ๋•Œ๋ฌธ์— ์–ด๋–ค ๊ฒฐ๊ณผ๋ฅผ ์–ป์„์ง€ ์˜ˆ์ธกํ•  ์ˆ˜ ์—†๋‹ค.
map.get(five) // ten? five??
  • ๋ถˆ๋ณ€ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ์ฒด๋ฅผ map์— ์ถ”๊ฐ€ํ•œ ํ›„์—๋Š” ์ƒํƒœ ๋ณ€๊ฒฝ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์‹๋ณ„์ž ๊ฐ€๋ณ€์„ฑ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค.

๐ŸŽˆ ์‹คํŒจ ์›์ž์„ฑ(Failure Atomicity)โ€‹

  • ์‹คํŒจ ์›์ž์„ฑ์ด๋ž€ ์™„์ „ํ•˜๊ณ  ๊ฒฌ๊ณ ํ•œ ์ƒํƒœ์˜ ๊ฐ์ฒด๋ฅผ ๊ฐ€์ง€๊ฑฐ๋‚˜ ์•„๋‹ˆ๋ฉด ์‹คํŒจํ•˜๊ฑฐ๋‚˜ ๋‘˜ ์ค‘ ํ•˜๋‚˜๋งŒ ๊ฐ€๋Šฅํ•œ ํŠน์„ฑ์ด๋‹ค.
  • ๋‹ค์Œ์€ ๊ฐ€๋ณ€ ํด๋ž˜์Šค Cash ์˜ˆ์ œ์ด๋‹ค.
class Cash {
private int dollars;
private int cents;

public void mul(int factor) {
this.dollars *= factor;

if (/* ๋ญ”๊ฐ€ ์ž˜๋ชป ๋๋‹ค๋ฉด */) {
throw new RuntimeException("oops...");
}

this.cents *= factor;
}
}
  • mul() ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋„์ค‘์— ์˜ˆ์™ธ๊ฐ€ ๋˜์ ธ์ง„๋‹ค๋ฉด ๊ฐ์ฒด์˜ ์ ˆ๋ฐ˜(this.dollars)๋งŒ ์ˆ˜์ •๋˜๊ณ  ๋‚˜๋จธ์ง€ ์ ˆ๋ฐ˜(this.cents)์€ ์›๋ž˜ ๊ฐ’์„ ์œ ์ง€ํ•œ๋‹ค.
  • ๋ถˆ๋ณ€ ๊ฐ์ฒด๋Š” ๋‚ด๋ถ€์˜ ์–ด๋–ค ๊ฒƒ๋„ ์ˆ˜์ •ํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ด๋Ÿฐ ๊ฒฐํ•จ์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค.
class Cash {
private int dollars;
private int cents;

public Cash mul(int factor) {
if (/* ๋ญ”๊ฐ€ ์ž˜๋ชป ๋๋‹ค๋ฉด */) {
throw new RuntimeException("oops...");
}

return new Cash(
this.dollars * factor,
this.cents * factor
);
}
}
  • ๋ถˆ๋ณ€ ๊ฐ์ฒด์˜ ์ •์˜์— ๋”ฐ๋ฅด๋ฉด ๋ชจ๋“  ๋ถˆ๋ณ€ ๊ฐ์ฒด๋Š” ์›์ž์ ์ด๊ธฐ ๋•Œ๋ฌธ์— ์›์ž์„ฑ์„ ๊ฑฑ์ •ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.
  • ๊ฐ€๋ณ€ ๊ฐ์ฒด ์•ˆ์—์„œ ๋ช…์‹œ์ ์œผ๋กœ ์‹คํŒจ ์›์ž์„ฑ์„ ๋ณด์žฅํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ์ง€๋งŒ ๊ฐ์ฒด์˜ ๋ณต์žก์„ฑ์ด ๋” ๋†’์•„์ง€๊ณ , ์‹ค์ˆ˜ํ•  ๊ฐ€๋Šฅ์„ฑ์ด ๋” ์ปค์ง€๊ธฐ ๋•Œ๋ฌธ์— ์ข‹์ง€ ์•Š๋‹ค.

๐ŸŽˆ ์‹œ๊ฐ„์  ๊ฒฐํ•ฉ(Temporal Coupling)โ€‹

  • ๋‹ค์Œ์€ ์‹œ๊ฐ„์  ๊ฒฐํ•ฉ์„ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋Š” ์ข‹์€ ๋ฐฉ๋ฒ•์ธ ์˜ˆ์ œ์ด๋‹ค.
Cash price = new Cash();
price.setDollars(29);
price.setCents(95);
System.out.println(price); // "$29.95"
  • ๊ฐ ์ค„์€ ํŠน์ •ํ•œ ์ˆœ์„œ๋กœ ์ •๋ ฌ๋˜์–ด ์žˆ๋‹ค. ๊ฐ ์ค„์€ ์‹œ๊ฐ„์ ์ธ ์ˆœ์„œ์— ๋”ฐ๋ผ ์„œ๋กœ ๊ฒฐํ•ฉ๋˜์–ด ์žˆ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ์žฌ์ •๋ ฌํ•ด๋„ ์ปดํŒŒ์ผ์€ ์—ฌ์ „ํžˆ ์„ฑ๊ณตํ•œ๋‹ค.
Cash price = new Cash();
price.setDollars(29);
System.out.println(price); // "$29.00"
price.setCents(95);
  • ์ด๋ ‡๊ฒŒ ์ค„ ์‚ฌ์ด์˜ ์‹œ๊ฐ„์ ์ธ ๊ฒฐํ•ฉ์„ ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ๊ธฐ์–ตํ•ด์•ผ ํ•œ๋‹ค. ์ด๋Ÿฌ๋ฉด ์œ ์ง€๋ณด์ˆ˜์— ์žˆ์–ด์„œ ์–ด๋ ค์›€์ด ํฌ๋‹ค.
  • ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ถˆ๋ณ€ ๊ฐ์ฒด๋ฅผ ์ด์šฉํ•˜์—ฌ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.
Cash price = new Cash(29, 95);
System.out.println(price); // "$29.95"
  • ์ด๋ ‡๊ฒŒ ํ•˜๋‚˜์˜ ๋ฌธ์žฅ์œผ๋กœ ๊ฐ์ฒด๋ฅผ ์ธ์Šคํ„ด์Šคํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด ๊ฒฝ์šฐ์—๋Š” ์ธ์Šคํ„ด์Šคํ™”์™€ ์ดˆ๊ธฐํ™”๋ฅผ ๋ถ„๋ฆฌ์‹œํ‚ฌ ์ˆ˜ ์—†๋‹ค. ํ•ญ์ƒ ํ•จ๊ป˜ ์‹คํ–‰๋˜์–ด์•ผ ํ•œ๋‹ค. ์ˆœ์„œ๋„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋‹ค.

๐ŸŽˆ ๋ถ€์ˆ˜ํšจ๊ณผ ์ œ๊ฑฐ(Side effect-free)โ€‹

  • ๋‹ค์Œ ์˜ˆ์ œ๋Š” ๊ฐ€๊ฒฉ์„ 2๋ฐฐ๋กœ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ์‹ค์ˆ˜๋ฅผ ์ €์งˆ๋ ธ๋‹ค.
void print(Cash price) {
System.out.println("Tody price is: " + price);
price.mul(2);
System.out.println(
"Buy now, tomorrow price is: " + price
);
}
  • ์ด์ œ ์ด ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๋ถ€์ˆ˜ํšจ๊ณผ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
Cash five = new Cash(5);
print(five);
System.out.println(five); // "$10"
  • ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ ์ง€์ ์„ ์ฐพ๊ธฐ ์œ„ํ•ด์„œ five ๊ฐ์ฒด๋ฅผ ์ˆ˜์ •ํ•œ ๋ชจ๋“  ๊ณณ์„ ๋””๋ฒ„๊น…ํ•ด์•ผ ํ•œ๋‹ค.
  • ๋ฐ˜๋ฉด์— Cash ํด๋ž˜์Šค๋ฅผ ๋ถˆ๋ณ€์œผ๋กœ ๋งŒ๋“ค๋ฉด ์–ด๋–ค ๋ˆ„๊ตฌ๋„ ๊ฐ์ฒด๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์—†๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ฐ์ฒด์˜ ์ƒํƒœ๊ฐ€ ๋ณ€ํ•˜์ง€ ์•Š์•˜๋‹ค๊ณ  ํ™•์‹ ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ฝ”๋“œ๊ฐ€ ์ œ๋Œ€๋กœ ๋™์ž‘ํ•˜์ง€ ์•Š์•„๋„ ๋ถ€์ˆ˜ํšจ๊ณผ๊ฐ€ ๋ฐœ์ƒํ•œ ์œ„์น˜๋ฅผ ์ฐพ์„ ํ•„์š”๊ฐ€ ์—†๋‹ค.

๐ŸŽˆ NULL ์ฐธ์กฐ ์—†์• ๊ธฐโ€‹

  • ์„ค์ •๋˜์ง€ ์•Š์€(unset) ํ”„๋กœํผํ‹ฐ์— ๊ด€ํ•œ ์˜ˆ์ œ์ด๋‹ค.
class User {
private final int id;
private String name = null;

public User(int num) {
this.id = num;
}

public void setName(String txt) {
this.name = txt;
}
}
  • ์ด ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ์ƒ์„ฑ๋  ๋•Œ name ํ”„๋กœํผํ‹ฐ์˜ ๊ฐ’์œผ๋กœ NULL์ด ํ• ๋‹น๋œ๋‹ค. ์ด ๊ฐ’์€ ๋‚˜์ค‘์— setName() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ์ดˆ๊ธฐํ™”๋˜๊ณ , ๊ทธ ์ „๊นŒ์ง€๋Š” ๊ฐ’์ด NULL์ธ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•œ๋‹ค.
  • NULL์€ ๋นˆ ๋ฌธ์ž์—ด๊ณผ ํฌ๊ฒŒ ๋‹ค๋ฅด์ง€ ์•Š๋‹ค. NULL์ด ์•„๋‹Œ์ง€ ์ฒดํฌํ•ด์•ผํ•˜๊ณ , ๋ฌธ์ œ๊ฐ€ ์—†๋Š”์ง€ ํ™•์ธํ•ด์•ผ ํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ฌธ์ œ๋Š” ์–ด๊น€์—†์ด ๋ฐœ์ƒํ•œ๋‹ค.
  • ๋” ํฐ ๋ฌธ์ œ๋Š” ์‹ค์ œ ๊ฐ’์ด ์•„๋‹Œ NULL์„ ์ฐธ์กฐํ•˜๋Š” ๊ฐ์ฒด๋Š” ์œ ์ง€๋ณด์ˆ˜์„ฑ์ด ์ €ํ•˜๋  ์ˆ˜ ๋ฐ–์— ์—†๋‹ค. ์–ธ์ œ ๊ฐ์ฒด๊ฐ€ ์œ ํšจํ•œ ์ƒํƒœ์ธ์ง€ ์–ธ์ œ ๊ฐ์ฒด๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ ํ˜•ํƒœ๋กœ ๋ฐ”๋€Œ๋Š” ์ง€๋ฅผ ์ดํ•ดํ•˜๊ธฐ๊ฐ€ ์–ด๋ ต๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
  • ๋ชจ๋“  ๊ฐ์ฒด๋ฅผ ๋ถˆ๋ณ€์œผ๋กœ ๋งŒ๋“ค๋ฉด ๊ฐ์ฒด ์•ˆ์— NULL์„ ํฌํ•จ์‹œํ‚ค๋Š” ๊ฒƒ์ด ์• ์ดˆ์— ๋ถˆ๊ฐ€๋Šฅํ•ด์ ธ ์ž‘๊ณ , ๊ฒฌ๊ณ ํ•˜๋ฉฐ,์‘์ง‘๋„ ๋†’์€ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ๋ฐ–์— ์—†๋„๋ก ๊ฐ•์ œ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์œ ์ง€๋ณด์ˆ˜ํ•˜๊ธฐ์— ํ›จ์”ฌ ๋” ์‰ฌ์šด ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ ๋‹ค.

๐ŸŽˆ ์Šค๋ ˆ๋“œ ์•ˆ์ •์„ฑ(Thread Safety)โ€‹

  • ์Šค๋ ˆ๋“œ ์•ˆ์ •์„ฑ์ด๋ž€ ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ์—์„œ ๋™์‹œ์— ์‚ฌ์šฉ๋  ์ˆ˜ ์ž‡์œผ๋ฉฐ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ํ•ญ์ƒ ์˜ˆ์ธก๊ฐ€๋Šฅํ•˜๋„๋ก ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ์ฒด์˜ ํ’ˆ์งˆ์„ ์˜๋ฏธํ•œ๋‹ค.
  • ๋ถˆ๋ณ€ ๊ฐ์ฒด๋Š” ์‹คํ–‰ ์‹œ์ ์— ์ƒํƒœ๋ฅผ ์ƒํƒœ๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์—†๊ฒŒ ๊ธˆ์ง€ํ•จ์œผ๋กœ์จ ๊ฒฐ๊ณผ๋ฅผ ํ•ญ์ƒ ์˜ˆ์ธก๊ฐ€๋Šฅํ•˜๋„๋ก ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค. ์–ด๋–ค ์Šค๋ ˆ๋“œ๋„ ๊ฐ์ฒด์˜ ์ƒํƒœ๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ€๋Šฅํ•˜๋‹ค.
  • ๋ช…์‹œ์ ์œผ๋กœ ๋™๊ธฐํ™”๋ฅผ ์ด์šฉํ•˜๋ฉด ๊ฐ€๋ณ€ ํด๋ž˜์Šค ์—ญ์‹œ ์Šค๋ ˆ๋“œ์— ์•ˆ์ „ํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜๋Š” ์žˆ๋‹ค.
class Cash {
private int dollars;
private int cents;

public void mul(int factor) {
synchronized (this) {
this.dollars *= factor;
this.cents *= factor;
}
}
}
  • ์ •์ƒ์ ์œผ๋กœ๋Š” ๋™์ž‘ํ•˜์ง€๋งŒ ๋ฌธ์ œ์ ์ด ์žˆ๋‹ค. ์ฒซ์งธ, ๊ฐ€๋ณ€ ํด๋ž˜์Šค์— ์Šค๋ ˆ๋“œ ์•ˆ์ „์„ฑ์„ ์ถ”๊ฐ€ํ•˜๋Š” ์ผ์€ ์ƒ๊ฐ์ฒ˜๋Ÿผ ์‰ฝ์ง€ ์•Š๋‹ค. ๋‘˜์งธ, ๋™๊ธฐํ™” ๋กœ์ง์„ ์ถ”๊ฐ€ํ•˜๋Š” ์ผ์€ ์„ฑ๋Šฅ์ƒ์˜ ๋น„์šฉ์„ ์ดˆ๋ž˜ํ•œ๋‹ค. ๊ฐ ์Šค๋ ˆ๋“œ๋Š” ๊ฐ์ฒด๋ฅผ ๋ฐฐํƒ€์ ์œผ๋กœ ์ž ๊ทธ๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค๋ฅธ ๋ชจ๋“  ์Šค๋ ˆ๋“œ๋Š” ๊ฐ์ฒด๊ฐ€ ํ•ด์ œ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ฌ๋ฆด ์ˆ˜๋ฐ–์— ์—†๋‹ค.
  • ์ด๋Ÿฐ ์ด์œ ๋กœ ๊ฐ€๋ณ€ ๊ฐ์ฒด๋ฅผ ํ”ผํ•˜๊ณ  ๋ถˆ๋ณ€ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

๐ŸŽˆ ๋” ์ž‘๊ณ  ๋” ๋‹จ์ˆœํ•œ ๊ฐ์ฒดโ€‹

  • ๊ฐ์ฒด๊ฐ€ ๋” ๋‹จ์ˆœํ•ด์งˆ ์ˆ˜๋ก ์‘์ง‘๋„๋Š” ๋” ๋†’์•„์ง€๊ณ , ์œ ์ง€๋ณด์ˆ˜ํ•˜๊ธฐ๋Š” ๋” ์‰ฌ์›Œ์ง„๋‹ค.
  • ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ, ๋‹จ์ˆœํ•˜๋‹ค๋Š” ๊ฒƒ์€ ๋” ์ ์€ ์ฝ”๋“œ ์ค„์ˆ˜๋ฅผ ์˜๋ฏธํ•œ๋‹ค. ํ•œ ํด๋ž˜์Šค ์•ˆ์— 1000์ค„์˜ ์ฝ”๋“œ๊ฐ€ ๋“ค์–ด์žˆ๋‹ค๋ฉด, ์ž‘์„ฑ์ž์กฐ์ฐจ๋„ ํด๋ž˜์Šค๊ฐ€ ์–ด๋–ค ์ผ์„ ํ•˜๋Š”์ง€ ๋ชจ๋ฅผ ๊ฒƒ์ด ๋ถ„๋ช…ํ•˜๋‹ค. ์ตœ๋Œ€ ํฌ๊ธฐ๋Š” ์ฃผ์„๊ณผ ๊ณต๋ฐฑ์„ ํฌํ•จํ•ด 250์ค„์ •๋„.. (์—ฌ๊ธฐ์„œ ์ฝ”๋“œ๋ž€ ํ”„๋กœ๋•์…˜ ์ฝ”๋“œ์™€ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ํฌํ•จ)
  • ๋ถˆ๋ณ€ ๊ฐ์ฒด๋Š” ์•„์ฃผ ํฌ๊ฒŒ ๋งŒ๋“œ๋Š” ์ผ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๊ณ , ์ผ๋ฐ˜์ ์œผ๋กœ ๋ถˆ๋ณ€ ๊ฐ์ฒด๋Š” ๊ฐ€๋ณ€ ๊ฐ์ฒด๋ณด๋‹ค ๋” ์ž‘๋‹ค. (๋ถˆ๋ณ€ ๊ฐ์ฒด๊ฐ€ ์ž‘์€ ์ด์œ ๋Š” ์ƒ์„ฑ์ž ์•ˆ์—์„œ๋งŒ ์ƒํƒœ๋ฅผ ์ดˆ๊ธฐํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.)

๐Ÿฆ„ ๋ฌธ์„œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋Œ€์‹  ํ…Œ์ŠคํŠธ๋ฅผ ๋งŒ๋“œ์„ธ์š”โ€‹

  • ๋ฌธ์„œํ™”๋Š” ์œ ์ง€๋ณด์ˆ˜์— ์žˆ์–ด ์ค‘์š”ํ•œ ๊ตฌ์„ฑ์š”์†Œ์ด๋‹ค.
  • ํด๋ž˜์Šค๋‚˜ ๋ฉ”์„œ๋“œ์— ๊ด€ํ•œ ์ถ”๊ฐ€์ •๋ณด์— ์–ผ๋งˆ๋‚˜ ์‰ฝ๊ฒŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ์ง€๊ฐ€ ์ค‘์š”ํ•˜๋‹ค.
  • ์ด์ƒ์ ์ธ ์ฝ”๋“œ๋Š” ์Šค์Šค๋กœ ์„ค๋ช…ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์–ด๋–ค ์ถ”๊ฐ€ ๋ฌธ์„œ๋„ ํ•„์š”ํ•˜์ง€ ์•Š๋Š”๋‹ค. ๋”ฐ๋ผ์„œ ์ฝ”๋“œ๋ฅผ ๋ฌธ์„œํ™”ํ•˜๋Š” ๋Œ€์‹  ์ฝ”๋“œ๋ฅผ ๊น”๋”ํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค.
  • ์—ฌ๊ธฐ์„œ ๊น”๋”ํ•˜๊ฒŒ ๋งŒ๋“ ๋‹ค๋ผ๋Š” ๋ง์—๋Š” ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋„ ํ•จ๊ป˜ ๋งŒ๋“ ๋‹ค๋Š” ์˜๋ฏธ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๋‹ค.
  • ๊น”๋”ํ•˜๊ณ  ์œ ์ง€๋ณด์ˆ˜ ๊ฐ€๋Šฅํ•œ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด, ํด๋ž˜์Šค๋ฅผ ๋” ๊น”๋”ํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ณ  ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค. ๋” ํ›Œ๋ฅญํ•œ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ• ์ˆ˜๋ก ๋” ์ ์€ ๋ฌธ์„œํ™”๊ฐ€ ์š”๊ตฌ๋œ๋‹ค. ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๊ฐ€ ๋ฐ”๋กœ ๋ฌธ์„œํ™”์ด๋‹ค.
  • ํ›Œ๋ฅญํ•˜๊ณ  ๊น”๋”ํ•œ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ ์ตœ๊ณ ์˜ ์กฐ์–ธ์€ ๋ฉ”์ธ ์ฝ”๋“œ๋งŒํผ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ์—๋„ ๊ด€์‹ฌ์„ ๊ธฐ์šธ์—ฌ์•ผ ํ•œ๋‹ค.
  • ๋‹ค์Œ์€ Cash ํด๋ž˜์Šค์˜ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ์ด๋‹ค.
class CashTest {
@Test
public void summarizes() {
assertThat(
new Cash("$5").plus(new Cash("$3")),
equalTo(new Cash("$8"))
);
}

@Test
public void deducts() {
assertThat(
new Cash("$7").plus(new Cash("-$11")),
equalTo(new Cash("-$4"))
);
}

@Test
public void multiplies() {
assertThat(
new Cash("$2").mul(3),
equalTo(new Cash("$6"))
);
}
}

๐Ÿฆ„ ๋ชจ์˜ ๊ฐ์ฒด(Mock) ๋Œ€์‹  ํŽ˜์ดํฌ ๊ฐ์ฒด(Fake)๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”โ€‹

  • ํ…Œ์ŠคํŠธ๋ฅผ ์ตœ์ ํ™”ํ•˜๊ธฐ ์œ„ํ•œ ๋„๊ตฌ์ธ ๋ชจํ‚น์ด๋‹ค.
  • ๋‹ค์Œ์€ ์ž๊ธฐ ์ž์‹ ์„ ์ƒˆ๋กœ์šด ํ™˜์œจ๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ๋Š” Cash ํด๋ž˜์Šค์ด๋‹ค.
class Cash {
private final Exchange exchange;
private final int cents;

public Cash(Exchange exch, int cnts) {
this.exchange = exch;
this.cents = cnts;
}

public Cash in(String currency) {
return new Cash(
this.exchange,
this.cents * this.exchange.rate(
"USD", currency
)
);
}
}
  • Cash๋Š” Exchangeํด๋ž˜์Šค์— ์˜์กดํ•˜๊ธฐ ๋•Œ๋ฌธ์— Cash ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” Exchange์˜ ์ธ์Šคํ„ด์Šค๋ฅผ Cash์˜ ์ƒ์„ฑ์ž์— ์ „๋‹ฌํ•ด์•ผ ํ•œ๋‹ค.
// NYSE ํด๋ž˜์Šค๋Š” USD์—์„œ EUR๋กœ ๋ณ€ํ™˜ํ•˜๊ธฐ ์œ„ํ•œ ํ™˜์œจ์„ ์ฐพ๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ๊ณ  ์žˆ๋‹ค.
// ํŒจ์Šค์›Œ๋“œ๋กœ secret์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค.
Cash dollar = new Cash(new NYSE("secret"), 100);
Cash euro = dollar.in("EUR");
  • ์šฐ๋ฆฌ๋Š” NYSE๊ฐ€ ๊ฐœ์ž…ํ•˜์ง€ ์•Š๊ณ  Cash ํด๋ž˜์Šค๋ฅผ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ•˜๋‹ค.
  • ์ „ํ†ต์ ์ธ ์ ‘๊ทผ๋ฐฉ์‹์€ ๋ชจํ‚น์œผ๋กœ NYSE๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€์‹  Exchange ์ธํ„ฐํŽ˜์ด์Šค์— ๋Œ€ํ•œ ๋ชจ์˜ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ ํ›„ Cash ์ƒ์„ฑ์ž์˜ ์ธ์ž๋กœ ์‚ฌ์šฉํ•œ๋‹ค.
Exchange exchange = Mockito.mock(Exchange.class);
Mockito.doReturn(1.15)
.when(exchange)
.rate("USD", "EUR")
Cash dollar = new Cash(exchange, 500);
Cash euro = dollar.in("EUR");
assert "5.75".equals(euro.toString());
  • ๋ชจํ‚น ๋Œ€์‹  ํŽ˜์ดํฌ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.
  • ๋‹ค์Œ์€ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ „๋‹ฌ๋  Exchange ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ตœ์ข… ์ฝ”๋“œ์ด๋‹ค.
interface Exchange {
float rate(String origin, String target);

final class Fake implements Exchange {
@Override
float rate(String origin, String target) {
return 1.2345;
}
}
}
  • ์ค‘์ฒฉ๋œ ํŽ˜์ดํฌ ํด๋ž˜์Šค๋Š” ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ผ๋ถ€์ด๋ฉฐ ์ธํ„ฐํŽ˜์ด์Šค์™€ ํ•จ๊ป˜ ์ œ๊ณต๋œ๋‹ค.
  • ์•„๋ž˜๋Š” ๋ชจํ‚น ๋Œ€์‹  ํŽ˜์ดํฌ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•œ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ์ด๋‹ค.
Exchange exchange = new Exchange.Fake();
Cash dollar = new Cash(exchange, 500);
Cash euro = dollar.in("EUR");
assert "6.17".equals(euro.toString());
  • ํŽ˜์ดํฌ ํด๋ž˜์Šค๋ฅผ ๋งŒ์กฑํ•˜๋„๋ก ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•˜์ง€ ๋ง๊ณ , ํŽ˜์ดํฌ ํด๋ž˜์Šค๊ฐ€ ํ…Œ์ŠคํŠธ๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ง€์›ํ•˜๋„๋ก ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค. ํŽ˜์ดํฌ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ…Œ์ŠคํŠธ๋ฅผ ๋” ์งง๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์œ ์ง€๋ณด์ˆ˜์„ฑ์ด ๋ˆˆ์— ๋„๊ฒŒ ํ–ฅ์ƒ๋œ๋‹ค.
  • ๋ฐ˜๋ฉด์— ๋ชจํ‚น์˜ ๊ฒฝ์šฐ, ํ…Œ์ŠคํŠธ๊ฐ€ ์žฅํ™ฉํ•ด์ง€๊ณ , ์ดํ•ดํ•˜๊ฑฐ๋‚˜ ๋ฆฌํŒฉํ† ๋งํ•˜๊ธฐ ์–ด๋ ค์›Œ์ง„๋‹ค. ๋˜ํ•œ, ๋ชจํ‚น์€ ๊ฐ€์ •์„ ์‚ฌ์‹ค๋กœ ์ „ํ™˜์‹œํ‚ค๊ธฐ ๋•Œ๋ฌธ์— ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋ฅผ ์œ ์ง€๋ณด์ˆ˜ํ•˜๊ธฐ ์–ด๋ ต๊ฒŒ ๋งŒ๋“ ๋‹ค.
  • ํด๋ž˜์Šค์˜ ํ–‰๋™์ด ๋ณ€๊ฒฝ๋˜๋ฉด ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํŒจํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๋‹จ์œ„ ํ…Œ์ŠคํŠธ์€ ์ฝ”๋“œ ๋ฆฌํŒฉํ† ๋ง์— ํฐ ๋„์›€์ด ๋œ๋‹ค. ํ•˜์ง€๋งŒ ๋™์‹œ์— ํ–‰๋™์ด ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์„ ๊ฒฝ์šฐ์—๋Š” ์‹คํŒจํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค.
  • ํ•˜์ง€๋งŒ ์•ž์—์„œ ์‚ดํŽด๋ณธ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋Š” ์•„๋ฌด๋Ÿฐ ์ด์œ  ์—†์ด๋„ ์‹คํŒจํ•  ์ˆ˜ ์žˆ๋‹ค. Exchange ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ˆ˜์ •ํ•œ๋‹ค.
interface Exchange {
float rate(String target);
float rate(String origin, String target);
}
  • ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณ€๊ฒฝํ•œ ํ›„ origin ํ†ตํ™”๊ฐ€ USD์ผ ๊ฒฝ์šฐ ํ•˜๋‚˜์˜ ์ธ์ž๋ฅผ ๋ฐ›๋Š” ์ƒˆ๋กœ์šด rate ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก Cash ํด๋ž˜์Šค๋ฅผ ์ˆ˜์ •ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๋ฉด, ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํŒจํ•  ๊ฒƒ์ด๋‹ค. ์•„๋ฌด ๊ฒƒ๋„ ์‹คํŒจํ•˜์ง€ ์•Š์•˜์ง€๋งŒ, ํ…Œ์ŠคํŠธ๋Š” ์‹คํŒจํ–ˆ๋‹ค๋Š” ์ž˜๋ชป๋œ ์‹ ํ˜ธ๋ฅผ ๋ณด๋‚ธ๋‹ค.
  • ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋Š” ๋„ˆ๋ฌด ์‰ฝ๊ฒŒ ๊นจ์ง€๊ณ  ๋ถˆ์•ˆ์ •ํ•˜๊ณ  ๋Œ€๋ถ€๋ถ„์˜ ์‹คํŒจ๋Š” ๋ชจํ‚น ๋•Œ๋ฌธ์— ์ผ์–ด๋‚œ๋‹ค.
  • ๋‹ค์Œ์€ ๋™์ผํ•œ ์ƒํ™ฉ์—์„œ Exchange ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ณ€๊ฒฝํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ž์—ฐ์ˆ˜๋Ÿฝ๊ฒŒ Exchange.Fake ํด๋ž˜์Šค์˜ ๊ตฌํ˜„๋„ ํ•จ๊ป˜ ๋ณ€๊ฒฝํ•ด์•ผ ํ•œ๋‹ค.
interface Exchange {
float rate(String target);
float rate(String origin, String target);

final class Fake implements Exchange {
@Override
float rate(String target) {
return this.rate("USD", target);
}

@Override
float rate(String origin, String target) {
return 1.2345;
}
}
}
  • ์œ„์™€ ๊ฐ™์ด ํŽ˜์ดํฌ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๊ฐ€ ๊นจ์ง€์ง€ ์•Š๋Š”๋‹ค.
  • ๋ชจํ‚น์€ ๋‚˜์œ ํ”„๋ž™ํ‹ฐ์Šค์ด๋‹ค. ๋ชจํ‚น์€ ํด๋ž˜์Šค ๊ตฌํ˜„๊ณผ ๊ด€๋ จ๋œ ๋‚ด๋ถ€ ์„ธ๋ถ€์‚ฌํ•ญ์„ ํ…Œ์ŠคํŠธ์™€ ๊ฒฐํ•ฉ์‹œํ‚จ๋‹ค.
  • ๋ฐ˜๋Œ€๋กœ ํŽ˜์ดํฌ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ…Œ์ŠคํŠธ๋ฅผ ์ถฉ๋ถ„ํžˆ ์œ ์ง€๋ณด์ˆ˜ ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค. Cash ํด๋ž˜์Šค์™€ Exchange ํด๋ž˜์Šค ์‚ฌ์ด์˜ ์˜์‚ฌ์†Œํ†ต ๋ฐฉ์‹์— ๋Œ€ํ•ด์„œ๋Š” ์‹ ๊ฒฝ ์“ธ ํ•„์š”๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
  • ํŽ˜์ดํฌ ํด๋ž˜์Šค์˜ ์ค‘์š”ํ•œ ์žฅ์  ํ•œ ๊ฐ€์ง€๋Š” ํŽ˜์ดํฌ ํด๋ž˜์Šค๋Š” ์ธํ„ฐํŽ˜์ด์Šค์˜ ์„ค๊ณ„์— ๊ด€ํ•ด ๋” ๊นŠ์ด ๊ณ ๋ฏผํ•˜๋„๋ก ํ•ด์ค€๋‹ค. ์ธํ„ฐํ„ฐ์ด์Šค๋ฅผ ์„ค๊ณ„ํ•˜๋ฉด์„œ ํŽ˜์ดํฌ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๋‹ค๋ณด๋ฉด ํ”Œ์—ฐ์ ์œผ๋กœ ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ž‘์„ฑ์ž๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์‚ฌ์š”์ž์˜ ๊ด€์ ์—์„œ๋„ ๊ณ ๋ฏผํ•œ๋‹ค. ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋‹ค๋ฅธ ๊ด€์ ์—์„œ ๋ฐ”๋ผ๋ณด๊ณ  ํ…Œ์ŠคํŠธ ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์‚ฌ์šฉ์ž์™€ ๋™์ผํ•œ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•œ๋‹ค.

๐Ÿฆ„ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์งง๊ฒŒ ์œ ์ง€ํ•˜๊ณ  ์Šค๋งˆํŠธ(smart)๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”โ€‹

  • ๋‘ ๊ฐœ์˜ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ๊ฐ๊ฐ 5๊ฐœ์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์„ ์–ธํ•˜๊ณ  ์žˆ๋‹ค๋ฉด, ๋‘ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ชจ๋‘ ๊ตฌํ˜„ํ•˜๋Š” ํด๋ž˜์Šค๋Š” 10๊ฐœ์˜ public ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ€์ง€๊ธฐ ๋•Œ๋ฌธ์— ์ด ํด๋ž˜์Šค๋ฅผ ์šฐ์•„ํ•˜๋‹ค๊ณ  ๋งํ•˜๊ธฐ๋Š” ์–ด๋ ต๋‹ค.
  • ์•ž ์„น์…˜์—์„œ ์„ค๋ช…ํ•œ Exchange ์ธํ„ฐํŽ˜์ด์Šค์ด๋‹ค.
interface Exchange {
float rate(String target);
float rate(String source, String target);
}
  • ์ด ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋„ˆ๋ฌด ๋งŽ์€ ๊ฒƒ์„ ์š”๊ตฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์„ค๊ณ„ ๊ด€์ ์—์„œ๋Š” ํ˜•ํŽธ ์—†๋Š” ์ธํ„ฐํŽ˜์ด์Šค์ด๋‹ค.
  • ์ด๋Ÿฐ ์ข…๋ฅ˜์˜ ๊ณ„์•ฝ์€ ๋‹จ์ผ ์ฑ…์ž„ ์›์น™์„ ์œ„๋ฐ˜ํ•˜๋Š” ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๋„๋ก ๋ถ€์ถ”๊ธด๋‹ค. ๋‹ค์‹œ ๋งํ•ด์„œ ์‘์ง‘๋„๊ฐ€ ๋‚ฎ์€ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ฒŒ ํ•œ๋‹ค.
  • ๋‘ rate ๋ฉ”์„œ๋“œ๋Š” ๋…๋ฆฝ์ ์ธ ํ•จ์ˆ˜์ด๋‹ค. ํ•˜๋‚˜์˜ ์ธ์ž๋ฅผ ๋ฐ›๋Š” rate ๋ฉ”์„œ๋“œ๋Š” ์ด ์ธํ„ฐํŽ˜์ด์Šค์— ํฌํ•จ๋˜์–ด์„œ๋Š” ์•ˆ๋œ๋‹ค.
  • ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ์œ„ํ•ด์„œ ์ธํ„ฐํŽ˜์ด์Šค ์•ˆ์— ์Šค๋งˆํŠธ ํด๋ž˜์Šค๋ฅผ ์ถ”๊ฐ€ํ•ด์„œ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.
interface Exchange {
float rate(String source, String target);

final class Smart {
private final Exchange origin;

public float toUsd(String source) {
return this.origin.rate(source, "USD");
}
}
}
  • ์ด ์Šค๋งˆํŠธ ํด๋ž˜์Šค๋Š” Exchange ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„๋˜๊ณ  ํ™˜์œจ์ด ์–ด๋–ป๊ฒŒ ๊ณ„์‚ฐ๋˜๋Š” ์ง€๋Š” ๋ชจ๋ฅด์ง€๋งŒ, ์ธํ„ฐํŽ˜์ด์Šค ์œ„์— ํŠน๋ณ„ํ•œ ๊ธฐ๋Šฅ์„ ์ ์šฉํ•œ๋‹ค. ์ด ๊ธฐ๋Šฅ์€ Exchange์˜ ์„œ๋กœ ๋‹ค๋ฅธ ๊ตฌํ˜„ ์‚ฌ์ด์— ๊ณต์œ ๋  ์ˆ˜ ์žˆ๋‹ค.
float rate = new Exchange.Smart(new NYSE()).toUsd("EUR");
  • ๋ชจ๋“  Exchange ๊ตฌํ˜„์ฒด์— ๋™์‹œ์— ๋” ๋งŽ์€ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•œ๋‹ค. EUR๋ผ๋Š” ๋ฌธ์ž์—ด ๋ฆฌํ„ฐ๋Ÿด์„ ๋ฐ˜๋ณต์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์ง€๋Š” ์•Š๋‹ค. ๋•Œ๋ฌธ์— eurToUsd() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
interface Exchange {
float rate(String source, String target);

final class Smart {
private final Exchange origin;

public float toUsd(String source) {
return this.origin.rate(source, "USD");
}

public float eurToUsd() {
return this.toUsd("EUR");
}
}
}
  • ์ด์ œ ๋‹จ ํ•œ๋ฒˆ์˜ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ๋งŒ์œผ๋กœ EUR์—์„œ USD๋กœ์˜ ํ™˜์œจ์„ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.
float rate = new Exchange.Smart(new NYSE()).eurToUsd();
  • ์Šค๋งˆํŠธ ํด๋ž˜์Šค์˜ ํฌ๊ธฐ๋Š” ์ ์  ๋” ์ปค์ง€๊ฒ ์ง€๋งŒ, Exchange ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์ž‘๊ณ , ๋†’์€ ์‘์ง‘๋„๋ฅผ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์งง๊ฒŒ ๋งŒ๋“ค๊ณ  ์Šค๋งˆํŠธ ํด๋ž˜์Šค๋ฅผ ์ธํ„ฐํŽ˜์ด์Šค์™€ ํ•จ๊ป˜ ๋ฐฐํฌํ•จ์œผ๋กœ์จ ๊ณตํ†ต ๊ธฐ๋Šฅ์„ ์ถ”์ถœํ•˜๊ณ  ์ฝ”๋“œ ์ค‘๋ณต์„ ํ”ผํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ด๋Ÿฌํ•œ ์ ‘๊ทผ๋ฐฉ๋ฒ•์€ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ์™€ ๋งค์šฐ ์œ ์‚ฌํ•˜๋‹ค. ํ…Œ์ฝ”๋ ˆ์ดํ„ฐ์™€ ์Šค๋งˆํŠธ ํด๋ž˜์Šค์™€ ๋‹ค๋ฅธ ์ ์€ ์Šค๋งˆํŠธ ํด๋ž˜์Šค๊ฐ€ ๊ฐ์ฒด์— ์ƒˆ๋กœ์šด ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š”๋ฐ ๋น„ํ•ด ํ…Œ์ฝ”๋ ˆ์ดํ„ฐ๋Š” ์ด๋ฏธ ์กด์žฌํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ข€ ๋” ๊ฐ•๋ ฅํ•˜๊ฒŒ ๋งŒ๋“ ๋‹ค๋Š” ์ ์ด๋‹ค.
interface Exchange {
float rate(String origin, String target);

final class Fast implements Exchange {
private final Exchange origin;

@Override
public float rate(String source, String target) {
final float rate;

if (source.equals(target)) {
rate = 1.0f;
} else {
rate = this.origin.rate(source, target);
}

return rate;
}

public float toUsd(String source) {
return this.origin.rate(source, "USD");
}
}
}
  • ์ค‘์ฒฉ ํด๋ž˜์Šค์ธ Exchange.Fast๋Š” ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ์ธ ๋™์‹œ์— ์Šค๋งˆํŠธ ํด๋ž˜์Šค์ด๋‹ค. ์ฒซ์งธ, Exchange.Fast๋Š” rate() ๋ฉ”์„œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•ด์„œ ๋” ๊ฐ•๋ ฅํ•˜๊ฒŒ ๋งŒ๋“ ๋‹ค. ๋‘˜์งธ, Exchange.Fast๋Š” ์ƒˆ๋กœ์šด ๋ฉ”์„œ๋“œ์ธ toUsd()๋ฅผ ์ถ”๊ฐ€ํ•ด์„œ USD๋กœ ์‰ฝ๊ฒŒ ํ™˜์œจ์„ ๋ณ€ํ˜ผํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ค€๋‹ค.