diff --git a/study/design-pattern/catalogs/prototype-pattern/ex1.png b/study/design-pattern/catalogs/prototype-pattern/ex1.png new file mode 100644 index 0000000..277a1cb Binary files /dev/null and b/study/design-pattern/catalogs/prototype-pattern/ex1.png differ diff --git a/study/design-pattern/catalogs/prototype-pattern/ex2.png b/study/design-pattern/catalogs/prototype-pattern/ex2.png new file mode 100644 index 0000000..d4a2769 Binary files /dev/null and b/study/design-pattern/catalogs/prototype-pattern/ex2.png differ diff --git a/study/design-pattern/catalogs/prototype-pattern/ex3.png b/study/design-pattern/catalogs/prototype-pattern/ex3.png new file mode 100644 index 0000000..284fb12 Binary files /dev/null and b/study/design-pattern/catalogs/prototype-pattern/ex3.png differ diff --git a/study/design-pattern/catalogs/prototype-pattern/ex4.png b/study/design-pattern/catalogs/prototype-pattern/ex4.png new file mode 100644 index 0000000..b5e0177 Binary files /dev/null and b/study/design-pattern/catalogs/prototype-pattern/ex4.png differ diff --git a/study/design-pattern/catalogs/prototype-pattern/ex5.png b/study/design-pattern/catalogs/prototype-pattern/ex5.png new file mode 100644 index 0000000..d7d0324 Binary files /dev/null and b/study/design-pattern/catalogs/prototype-pattern/ex5.png differ diff --git a/study/design-pattern/catalogs/prototype-pattern/index.md b/study/design-pattern/catalogs/prototype-pattern/index.md new file mode 100644 index 0000000..13b1368 --- /dev/null +++ b/study/design-pattern/catalogs/prototype-pattern/index.md @@ -0,0 +1,164 @@ +# ์›ํ˜• (PROTOTYPE) + +## ๐Ÿ’ก ์ฑ…์—์„œ ์„ค๋ช…ํ•˜๋Š” ์˜๋„ + +"์›ํ˜•์ด ๋˜๋Š”(Prototypical) ์ธ์Šคํ„ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ƒ์„ฑํ•  ๊ฐ์ฒด์˜ ์ข…๋ฅ˜๋ฅผ ๋ช…์‹œํ•˜๊ณ , ์ด๋ ‡๊ฒŒ ๋งŒ๋“  ๊ฒฌ๋ณธ์„ ๋ณต์‚ฌํ•ด์„œ ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค." (๊ฐ์ฒด ์ƒ์„ฑ ํŒจํ„ด) + +## ๐Ÿง ์šฐ๋ฆฌ ์ƒํ™ฉ์— ๋งž๊ฒŒ ํ’€์–ด ์“ด ๋™๊ธฐ + +- ์‚ฌ์‹ค ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ํ”„๋กœํ† ํƒ€์ž… ๊ธฐ๋ฐ˜ ์–ธ์–ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.. +- ๋น„๋ก GoF์˜ ํ”„๋กœํ† ํƒ€์ž… ํŒจํ„ด์—์„œ์ฒ˜๋Ÿผ clone() ์—ฐ์‚ฐ์˜ ๊ตฌํ˜„์ด ์—†๊ณ  ์–ธ์–ด ๋ ˆ๋ฒจ์—์„œ ๊ฐ์ฒด ์ƒ์„ฑ์‹œ์— ์ž๋™์œผ๋กœ ํ”„๋กœํ† ํƒ€์ž…์„ ์—ฐ๊ฒฐํ•ด์ฃผ๊ณ  ์žˆ์–ด์„œ ์ข€ ๋‹ค๋ฅด๊ธด ํ•˜์ง€๋งŒ, ๊ฐ์ฒด ์ƒ์„ฑ์‹œ์— ์›ํ˜•์— ๋Œ€ํ•œ ๋ ˆํผ๋Ÿฐ์Šค๋ฅผ ๋ณต์‚ฌํ•œ๋‹ค๋Š” ์ปจ์…‰์—์„œ๋Š” ๊ฐ™๋‹ค๊ณ  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +- ํ”„๋กœํ† ํƒ€์ž…์„ ํ†ตํ•œ ์ƒ์†(์œ„์ž„)์„ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ๋Š” ์ฃผ๋กœ ๋น„์Šทํ•œ ๊ธฐ๋Šฅ์„ ๊ฐ€์ง„ ํด๋ž˜์Šค(ํ•จ์ˆ˜)๊ฐ€ ๋งŽ์•„ ์กŒ์„ ๊ฒฝ์šฐ๋ฅผ ์ƒ๊ฐํ•ด ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ๋“ค๋ฉด, ๋ฉ”์‰ฌ์›์˜ ListStore ํด๋ž˜์Šค์™€ ์ด ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•˜๋Š” ์—ฌ๋Ÿฌ Store ํด๋ž˜์Šค๋“ค์„ ์ƒ๊ฐํ•ด๋ณด์„ธ์š”. ์„œ๋กœ ๋น„์Šทํ•œ ๊ธฐ๋Šฅ (search, ๋“ฑ๋“ฑ...) ๊ณผ ์†์„ฑ์„ ๊ฐ–๊ณ  ์žˆ์œผ๋ฉด์„œ ํŠน์ • ์ƒํƒœ๋ฅผ ๋ฏธ๋ฆฌ ListStore์—์„œ ์ดˆ๊ธฐํ™” ํ•ด์ฃผ๊ณ  ์žˆ์–ด์„œ ๊ฐœ๋ณ„ ์Šคํ† ์–ด๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ๋งˆ๋‹ค ์ดˆ๊ธฐํ™”ํ•ด์ฃผ๋Š” ์ˆ˜๊ณ ๋กœ์›€์ด ์ค„์–ด๋“ฆ๋‹ˆ๋‹ค. ๋˜ํ•œ ๋ณต์ œํ•  ํ•„์š”๊ฐ€ ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋“ค์„ ๋ฏธ๋ฆฌ ListStore์— ํ•„์š”ํ•˜๋‹ค๋ฉด ๋‹ด์•„๋‘๊ณ  ์ด ์›ํ˜•์„ ๋ณต์‚ฌํ•ด์„œ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. +- ๋ชจ๋ธ ํด๋ž˜์Šค๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ชจ๋ธ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒฝ์šฐ์—๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +## ๐Ÿ›  ํ™œ์šฉ์„ฑ: ์ด๋Ÿด ๋•Œ ์”๋‹ˆ๋‹ค + +- ๊ฐ์ฒด ์ƒ์„ฑ์— ๋น„์šฉ์ด ๋งŽ์ด ๋“œ๋Š” ๊ฒฝ์šฐ + +## ๐ŸŽ ๊ฒฐ๊ณผ + +- ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. +- ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ์„ฑ์ด ๋†’์•„์ง„๋‹ค. +- (์‚ฌ์‹ค ์›ํ˜• ํŒจํ„ด ์ž์ฒด๊ฐ€ ๋™์ ์ด๊ณ  1๊ธ‰ ๊ฐ์ฒด๋ฅผ ๋‹ค๋ฃจ๋Š” ์–ธ์–ด์—์„œ๋Š” ์ด๋“์ด ๋ณ„๋กœ ์ฒด๊ฐ๋˜์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.) + +## ๐Ÿ—บ ๊ตฌํ˜„ ๋ฐฉ๋ฒ• + +- ์ฑ…์— ๋‚˜์˜จ๋Œ€๋กœ์˜ ์ปจ์…‰.. + +```tsx +/** + * The example class that has cloning ability. We'll see how the values of field + * with different types will be cloned. + */ +class Prototype { + public primitive: any; + public component: object; + public circularReference: ComponentWithBackReference; + + public clone(): this { + const clone = Object.create(this); + + clone.component = Object.create(this.component); + + // Cloning an object that has a nested object with backreference + // requires special treatment. After the cloning is completed, the + // nested object should point to the cloned object, instead of the + // original object. Spread operator can be handy for this case. + clone.circularReference = { + ...this.circularReference, + prototype: { ...this }, + }; + + return clone; + } +} + +class ComponentWithBackReference { + public prototype; + + constructor(prototype: Prototype) { + this.prototype = prototype; + } +} + +/** + * The client code. + */ +function clientCode() { + const p1 = new Prototype(); + p1.primitive = 245; + p1.component = new Date(); + p1.circularReference = new ComponentWithBackReference(p1); + + const p2 = p1.clone(); + if (p1.primitive === p2.primitive) { + console.log( + "Primitive field values have been carried over to a clone. Yay!" + ); + } else { + console.log("Primitive field values have not been copied. Booo!"); + } + if (p1.component === p2.component) { + console.log("Simple component has not been cloned. Booo!"); + } else { + console.log("Simple component has been cloned. Yay!"); + } + + if (p1.circularReference === p2.circularReference) { + console.log("Component with back reference has not been cloned. Booo!"); + } else { + console.log("Component with back reference has been cloned. Yay!"); + } + + if (p1.circularReference.prototype === p2.circularReference.prototype) { + console.log( + "Component with back reference is linked to original object. Booo!" + ); + } else { + console.log("Component with back reference is linked to the clone. Yay!"); + } +} + +clientCode(); +``` + +- ํ•˜์ง€๋งŒ ์ด๋ ‡๊ฒŒ ์‚ฌ์šฉํ•  ์ผ์ด ์—†์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. +- ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ํ”„๋กœํ† ํƒ€์ž… ์ฒด์ธ์„ ์—ฐ๊ฒฐํ•˜๋Š” ๊ฐ์ฒด ์ƒ์„ฑ + +```jsx +// class ๋ฌธ๋ฒ• +class Bar { + constructor(x) { + this.x = x; + } + getX() { + return this.x; + } +} + +// ์ƒ์„ฑ์ž ํ•จ์ˆ˜ +function Bar(x) { + this.x = x; +} + +Bar.prototype.getX = function getX() { + return this.x; +}; + +// ์ด ๋‘˜์€ ๊ฐ™๋‹ค. +``` + +- ์ด ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ–ˆ์„ ๋•Œ, + ![ex1](ex1.png) + - ์ด๋ ‡๊ฒŒ ์ธ์Šคํ„ด์Šค ๊ฐ์ฒด์— ๋Œ€ํ•œ Shape์™€ ํ”„๋กœํ† ํƒ€์ž… ๊ฐ์ฒด๋ฅผ ๊ณต์œ ํ•ฉ๋‹ˆ๋‹ค. + +## ๐Ÿ”™ ์šฐ๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ•œ ์˜ˆ์‹œ (๋˜๋Š” ์šฐ๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ–ˆ๋‹ค๋ฉด...) + +- ๋ชจ๋ธ ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ + +์ฐธ๊ณ  + +V8์—”์ง„์—์„œ ํ”„๋กœํ† ํƒ€์ž… ๊ฐ์ฒด ์ ‘๊ทผ์‹œ ์ตœ์ ํ™” + +![ex2](ex2.png) + +- Shape๋Š” ๊ฐ์ฒด์˜ property์ด๋ฆ„๊ณผ ๊ทธ ํ”„๋กœํผํ‹ฐ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ value๋งŒ ์ œ์™ธํ•˜๊ณ  ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  value์— ๋Œ€ํ•œ ์˜คํ”„์…‹์„ ๊ฐ–๊ณ ์žˆ์–ด์„œ ๊ฐ์ฒด์— ์ €์žฅ๋œ ๋ฐธ๋ฅ˜์— ๋ฐ”๋กœ ์ ‘๊ทผํ•ฉ๋‹ˆ๋‹ค. + +![ex3](./ex3.png) + +- ๋จผ์ € foo์—์„œ getX๊ฐ€ ์žˆ๋Š”์ง€ ์ฒดํฌํ•ฉ๋‹ˆ๋‹ค. +- ๋‘๋ฒˆ์งธ๋กœ Bar.prototype์ด foo์˜ ๋ฐ”๋กœ ์ƒ์œ„ ํ”„๋กœํ† ํƒ€์ž…์ด ๋งž๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. +- ์„ธ๋ฒˆ์งธ๋กœ Bar.prototype์— getX๊ฐ€ ์žˆ๋Š”์ง€ ์ฒดํฌํ•ฉ๋‹ˆ๋‹ค. +- ์ด๋Ÿฐ์‹์œผ๋กœ ์ด 3๋ฒˆ์˜ ์ฒดํฌ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. (1 + 2N) N์€ ํ”„๋กœํ† ํƒ€์ž…์˜ ๊ฐฏ์ˆ˜ +- ์†๋„ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•ด V8์—”์ง„์—์„œ๋Š” ํ”„๋กœํ† ํƒ€์ž… ์ฒดํฌํ•˜๋Š” ํšŸ์ˆ˜๋ฅผ ์ค„์ด๊ธฐ๋กœ ํ•ฉ๋‹ˆ๋‹ค. + +![ex4](./ex4.png) + +- Shape + +![ex5](./ex5.png) + +- ๊ฐ ํ”„๋กœํ† ํƒ€์ž…์— ๋Œ€ํ•œ Shape๋ฅผ ๋‘๊ณ , prototype๊ฐ์ฒด๊ฐ€ ๋ณ€ํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด validityCell์˜ valid ์†์„ฑ์€ true๋กœ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค. +- ์ธ๋ผ์ธ ์บ์‹œ์—์„œ๋Š” ํ•ด๋‹น ํ”„๋กœํผํ‹ฐ๊ฐ€ ๋ฐœ๊ฒฌ๋œ ํ”„๋กœํ† ํƒ€์ž…๊ณผ +- ๋‘๋ฒˆ์งธ ์กฐํšŒ์‹œ์— ์ธ๋ผ์ธ์บ์‹œ๋ฅผ hitํ•˜๋ฉด ์—”์ง„์—์„œ๋Š” ์ธ์Šคํ„ด์Šค์˜ shape์™€ validity cell์„ ์ฒดํฌํ•˜๊ณ  valid ํ•˜๋‹ค๋ฉด ์—”์ง„์€ ๊ธฐ์–ตํ•˜๊ณ  ์žˆ๋Š” ํ”„๋กœํ† ํƒ€์ž…์˜ offset์œผ๋กœ ์ง์ ‘ ์ ‘๊ทผํ•ด์„œ ์ถ”๊ฐ€ ์กฐํšŒ๋ฅผ ์ƒ๋žตํ•ฉ๋‹ˆ๋‹ค. +- ์ด๋ ‡๊ฒŒ ํ•˜๋Š” ๊ฒฝ์šฐ ์†๋„๊ฐ€ ์ข€ ๋” ์ตœ์ ํ™”๋ฉ๋‹ˆ๋‹ค.