Design Patterns - Sizuha/devdog GitHub Wiki
๋์์ธ ํจํด์์ ๋ฐฐ์ฐ๋ ์ค๊ณ ์์น
- if(switch ํฌํจ) ๋์ ์์๊ณผ ๋คํ์ฑ ํ์ฉํ๋ค
- ์ธํฐํ์ด์ค ์ค์ฌ ์ค๊ณ
- ๋ณ๊ฒฝ์ด ๋ฐ์๋ ๋ถ๋ถ์ ๋ํด, ์ฌ์ฉ์๋ฅผ ์ํ ๊ณตํต๋ ์ธํฐํ์ด์ค๋ฅผ ์ ๊ณตํ๊ณ , ์ธ๋ถ์ ์ธ ๋ด์ฉ์ ๊ทธ ์ธํฐํ์ด์ค๋ฅผ ์์ ๋ฐ์์ ๊ตฌํํ์ฌ ๋ฏธ๋์ ๋ณ๋์ฌํญ์ ๋๋นํ๋ค.
๊ฐ์ฒด ์์ฑ์ ๊ดํ ํจํด
๊ณตํต์ ๋ฌธ์ ์ํฉ : ์์
๊ฒ์์์ ์ฌ์ฉ๋๋ ๊ฒ์ ์บ๋ฆญํฐ๋ฅผ ์ ์ํ Character Class๊ฐ ์๋ค.
๊ฒ์ ์บ๋ฆญํฐ๋ ์ ์ฌ(Fighter), ๊ถ์(Archer), ๋ง๋ฒ์ฌ(Wizard)๋ก ๊ฐ๊ฐ ์ง์ ์ด ๊ตฌ๋ถ๋์ด ์๋ค.
ํ๋ ์ด์ด๋ ์ด๋ค ์ง์ ์ค์ ํ๋๋ฅผ ์ ํํด์ ํ๋ ์ด ํ๊ฒ ๋๋ค.
์ด๊ฒ์ ๊ตฌํํ๊ธฐ ์ํ ์ ์ ํ ์ค๊ณ๋ฅผ ์ฐพ์๋ณด์.
Abstract Factory
๋ฌธ์ ์ํฉ
- ์ ํ๊ตฐ์ ์กด์ฌ
- ์ฌ๋ฌ ์ข ๋ฅ์ ๊ฐ์ฒด๋ค์ด ์กด์ฌํ๋ ์ํ์์,๊ทธ ๊ฐ์ฒด๋ค์ด ๋ค์ ์ฌ๋ฌ ์ข ๋ฅ์ ์ ํ๊ตฐ์ผ๋ก ๊ทธ๋ฃนํ ๋๋ ๊ฒฝ์ฐ
- ์ ํ๊ตฐ์ด ์กฐํฉ๋์ด์ง๋ ๊ฒฝ์ฐ์ ์๊ฐ ๋ง์์ง ๊ฒฝ์ฐ์ ๋ํ ๋ฌธ์ .
๊ตฌํ
์์ ๋์จ ๊ณตํต์ ๋ฌธ์ ์ํฉ์ ์๋ก ๋ค๋ฉด,
// ๊ฒ์ ์บ๋ฆญํฐ์ ๋ํ ๊ณตํต์ ์ ์
class Character {
public Vector2 position; // ์บ๋ฆญํฐ์ ํ์ฌ ์์น
public int hp;
public Character(int hp) {
this.hp = hp;
}
public float getDistanceFrom(Character target) {
return Math.sqrt( Math.pow(target.position.x - this.position.x, 2) + Math.pow(target.position.y - this.position.y, 2) );
}
public void defense(int damage) {
hp -= damage;
}
}
interface Weapon {
int getAttackRange();
int getDamage();
}
class Sword : Weapon {
public int getAttackRange() { return 1; }
public int getDamage() { return 10; }
}
class Bow : Weapon {
public int getAttackRange() { return 5; }
public int getDamage() { return 5; }
}
class Staff : Weapon {
public int getAttackRange() { return 5; }
public int getDamage() { return 5; }
}
interface Defender {
int getDef();
}
class NoneDefense : Defender {
public int getDef() { return 0; }
}
class Shield : Defender {
public int getDef() { return 2; }
}
class MagicShield : Defender {
public int getDef() { return 1; }
}
//----- ํ๋ ์ด์ด์ ์ก์
์ ์ํํ๋ ๋ถ๋ถ -------
class GameManager {
public void attack(Character atkChr, Character defChr) {
var distance = atkChr.getDistanceFrom(defChr);
if (distance <= atkChr.weapon.getAttackRange()) {
var damage = atkChr.weapon.getDamage() - defChr.defender.getDef();
defChr.defense(damage);
}
}
}
์ด์ ํ๋ ์ด์ด๊ฐ ์์ ์ด ์ ํํ ์ง์ ์ ๋ํด์, ๊ทธ์ ๋ง๋ ์บ๋ฆญํฐ๋ฅผ ์์ฑํ๊ณ , ์ง์ ๋ณ๋ก ๋ฌด๊ธฐ์ ๋ฐฉ์ด๊ตฌ๋ฅผ ์์ฑํด ์ฃผ์ด์ผ ํ๋ค. ํ์ง๋ง, ๊ทธ์ธ ๊ณต๊ฒฉ์ด๋ ๋ฐฉ์ด์ ๋ํ ๋ก์ง์ ๋ณํจ์ด ์๋ค.
์ด๋ ์บ๋ฆญํฐ ์ง์ ์ ํ๋์ ์ ํ๊ตฐ์ผ๋ก ๋ณด๊ณ , ๊ฐ ์ง์ ๋ณ๋ก ํฉํ ๋ฆฌ ํด๋์ค๋ฅผ ํ๋์ฉ ์ ์ํด ๋๊ฐ๋ค.
// ์ ํ๊ตฐ์ ๋ํ ์ธํฐํ์ด์ค
interface PlayerJobFactory {
Character createCharacter();
Weapon createWeapon();
Defender createDefender();
}
class FighterFactory : PlayerJobFactory {
public Character createCharacter() { new Character(200); }
public Weapon createWeapon() { new Sword(); }
public Defender createDefender() { new Shield(); }
}
class ArcherFactory : PlayerJobFactory {
public Character createCharacter() { new Character(150); }
public Weapon createWeapon() { new Bow(); }
public Defender createDefender() { new NoneDefense(); }
}
class WizardFactory : PlayerJobFactory {
public Character createCharacter() { new Character(100); }
public Weapon createWeapon() { new Staff(); }
public Defender createDefender() { new MagicShield(); }
}
Factory Method
๋ฌธ์ ์ํฉ
- ์ด๋ ํ ํด๋์ค ๋ด์์ ์ฌ์ฉ๋๋ ๋์ ๊ฐ์ฒด๊ฐ ์ฌ๋ฌ ์ข ๋ฅ๊ฐ ์๊ณ ,
- ๊ทธ ์ค์์ ๊ฒฝ์ฐ์ ๋ฐ๋ผ ํ๋๋ฅผ ์ ํํด์ ์์ฑํ๊ฒ ๋๋ ๊ฒฝ์ฐ
- ์ฆ, ๊ฐ์ฒด ์์ฑ๊ณผ์ ์์ ๊ฒฝ์ฐ์ ์๊ฐ ๋ฐ์
๊ตฌํ
์์์ ์ถ์ ํด๋์ค์์ ๊ฐ์ฒด ์์ฑ์ ์ํ ํฉํ ๋ฆฌ ๋ฉ์๋ ์ธํฐํ์ด์ค๋ฅผ ๋ง๋ค์ด ๋๊ณ , ์ค์ ๊ฐ์ฒด์ ์์ฑ์ ํ์ ํด๋์ค์ ํฉํ ๋ฆฌ ๋ฉ์๋์์ ์ฒ๋ฆฌํ๊ฒ ํ๋ค.
// ๊ฒ์ ์บ๋ฆญํฐ์ ๋ํ ๊ณตํต์ ์ ์
abstract class Character {
public Vector2 position; // ์บ๋ฆญํฐ์ ํ์ฌ ์์น
public int hp;
Weapon weapon;
Defender defender;
public Character(int hp) {
this.hp = hp;
weapon = createWeapon();
defender = createDefender();
}
abstract protected Weapon createWeapon();
abstract protected Defender createDefender();
public float getDistanceFrom(Character target) {
return Math.sqrt( Math.pow(target.position.x - this.position.x, 2) + Math.pow(target.position.y - this.position.y, 2) );
}
public void defense(int damage) {
hp -= damage - defender.getDef();
}
public void attack(Character defChr) {
var distance = getDistanceFrom(defChr);
if (distance <= weapon.getAttackRange()) {
var damage = weapon.getDamage();
defChr.defense(damage);
}
}
}
//---- ์ง์
๋ณ ์ ์ -------
class Fighter : Character {
public Fighter() : base(200) {}
protected Weapon createWeapon() { return new Sword();}
protected Defender createDefender() { new Shield(); }
}
class Archer : Character {
public Archer() : base(150) {}
protected Weapon createWeapon() { return new Bow();}
protected Defender createDefender() { new NoneDefense(); }
}
class Wizard : Character {
public Wizard() : base(100) {}
protected Weapon createWeapon() { return new Staff();}
protected Defender createDefender() { new MagicShield(); }
}
Builder
๋ฌธ์ ์ํฉ
- ๊ฐ์ฒด ์์ฑ์ ํ์ํ ์ ๋ณด๋ฅผ ์์งํ๋ ์์ ๊ณผ, ์ค์ ๊ฐ์ฒด๋ฅผ ์์ฑํด์ผ ๋๋ ์์ ์ ๊ฒฉ์ฐจ๊ฐ ์๋ ๊ฒฝ์ฐ,
- ๊ฐ์ฒด ์์ฑ ๊ณผ์ ์ ๋จ๊ณ์ ์ผ๋ก ์งํํ๊ฒ ํด์ผ๋๋ ๊ฒฝ์ฐ
- ๊ฐ์ฒด ์์ฑ ๊ณผ์ ์์, ๋ค์ํ ์ต์ ์ ๋ถ์ฌํด์ผ ๋๋ ๊ฒฝ์ฐ
๊ตฌํ
- ๋ชฉ์ ์ด ๋๋ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ธฐ ์ํ ๋น๋ ํด๋์ค๋ฅผ ๊ตฌํํ๋ค.
- ๋น๋ ํด๋์ค๋ ๋ชฉ์ ๊ฐ์ฒด๋ฅผ ๋ง๋ค๊ธฐ ์ํ ์ ๋ณด๋ฅผ ์ ํ ํ๊ธฐ ์ํ ์ธํฐํ์ด์ค๋ฅผ ์ ๊ณต.
- ์ต์ข ์ ์ผ๋ก ์ง์ ๊น์ง ์์ง๋ ์ ๋ณด๋ฅผ ๋ฐํ์ผ๋ก ๋ชฉ์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ธฐ ์ํ ๋ฉ์๋๋ฅผ ์ ๊ณตํ๋ค.
class Character {
public string name;
public Vector2 position; // ์บ๋ฆญํฐ์ ํ์ฌ ์์น
public int hp;
public Weapon weapon;
public Defender defender;
public Character(string name, Vector2 position, int hp, Weapon weapon, Defender defender) {
// ...
}
public float getDistanceFrom(Character target) {
return Math.sqrt( Math.pow(target.position.x - this.position.x, 2) + Math.pow(target.position.y - this.position.y, 2) );
}
public void defense(int damage) {
hp -= damage - defender.getDef();
}
public void attack(Character defChr) {
var distance = getDistanceFrom(defChr);
if (distance <= weapon.getAttackRange()) {
var damage = weapon.getDamage();
defChr.defense(damage);
}
}
}
class ChracterBuilder {
string name;
int hp;
Vector2 pos;
Weapon w;
Defender d;
public ChracterBuilder() {}
public ChracterBuilder setName(string name) { this.name = name; return this; }
public ChracterBuilder setHP(int hp) { this.hp = hp; return this; }
public ChracterBuilder setPosition(Vector2 pos) { this.pos = pos; return this; }
public ChracterBuilder setWeapon(Weapon weapon) { w = weapon; return this; }
public ChracterBuilder setDefender(Defender defender) { d = defender; return this; }
public Character createCharacter() {
return new Character(name, pos, hp, w, d);
}
}
// ์ฌ์ฉ์:
void createFighter() {
Character player =
new ChracterBuilder()
.setName("Player")
.setHP(200)
.setWeapon(new Sword())
.setDefender(new Shield())
.createCharacter();
// . . .
}
MVC
MVCใฎๅ ธๅ็ใช็ธ้ขๅณ MVC๏ผModel View Controller ใขใใซใปใใฅใผใปใณใณใใญใผใฉ๏ผใฏใใฆใผใถใผใคใณใฟใใงใผในใใใคใขใใชใฑใผใทใงใณใฝใใใฆใงใขใๅฎ่ฃ ใใใใใฎใใถใคใณใใฟใผใณใงใใใ
ใขใใชใฑใผใทใงใณใฝใใใฆใงใขใฎๅ ้จใใผใฟใใใฆใผใถใผใ็ดๆฅๅ็ งใป็ทจ้ใใๆ ๅ ฑใใๅ้ขใใใใใฎใใใซใขใใชใฑใผใทใงใณใฝใใใฆใงใขใไปฅไธใฎ3ใคใฎ้จๅใซๅๅฒใใใ
- model: ใขใใชใฑใผใทใงใณใใผใฟใใใธใในใซใผใซใใญใธใใฏใ้ขๆฐ
- view: ใฐใฉใใๅณใชใฉใฎไปปๆใฎๆ ๅ ฑ่กจ็พ
- controller: ๅ ฅๅใๅใๅใmodelใจviewใธใฎๅฝไปคใซๅคๆใใ