"안녕, 아미고!"

"안녕, 빌라보!"

"오늘 우리의 주제는 단지 흥미롭기만 한 것이 아니라 완전히 서사적일 것입니다."

"오늘은 디자인 패턴이 무엇인지 알려드리겠습니다 . "

"멋지다! 나는 그들에 대해 많이 들었다. 나는 기다릴 수 없다!"

"숙련된 프로그래머는 많은 클래스를 작성해야 합니다. 그런데 이 작업에서 가장 어려운 부분은 어떤 클래스를 만들고 그 사이에 작업을 어떻게 분담할지 결정하는 것입니다."

"그런 질문을 더 많이 풀수록 일부 솔루션은 좋은 반면 다른 솔루션은 나쁘다는 것을 더 많이 깨달았습니다."

"잘못된 솔루션은 일반적으로 해결하는 것보다 더 많은 문제를 생성합니다. 제대로 확장되지 않고 불필요한 제한이 많이 발생하는 등 좋은 솔루션은 그 반대입니다."

"당신이 할 수 있는 비유가 있습니까?"

"당신이 집을 짓고 있다고 가정해 봅시다. 그리고 무엇으로 만들 것인지 생각하고 있습니다. 벽, 바닥, 천장이 필요하다고 결정합니다. 결과적으로 평평한 지붕과 그런 집은 금이 가고 지붕이 새게 됩니다. 이것은 나쁜 해결책입니다."

"반대로 토대, 벽, 박공 지붕으로 구성된 집이 좋은 해결책이 될 것입니다. 폭설이 내려도 문제 없습니다. 우리는 그러한 솔루션을 좋은 것이라고 부를 것입니다."

"알겠습니다. 감사합니다."

"알았어. 그럼 계속할게."

"시간이 흐르면서 좋은 솔루션은 디자인 패턴으로 알려지게 되었고, 나쁜 솔루션은 안티패턴으로 알려지게 되었습니다."

"디자인 패턴은 질문에 대한 답과 같습니다. 질문을 들어본 적이 없다면 이해하기 어렵습니다."

" 패턴의 첫 번째 범주는 생성 패턴입니다. 이러한 패턴은 객체 생성과 관련된 좋은 솔루션을 설명합니다."

"객체를 만드는 것이 뭐가 그리 복잡합니까?"

"공교롭게도, 그것이 바로 우리가 지금 탐구할 것입니다."

싱글톤 패턴.

디자인 패턴: 싱글톤, 팩토리, 팩토리 메소드, 추상 팩토리 - 1

"종종 프로그램에서 일부 개체의 단일 복사본만 존재할 수 있습니다. 예를 들어 콘솔, 로거, 가비지 수집기 등"

" 나쁜 솔루션: 개체를 만들지 마세요. 메서드가 모두 정적인 클래스를 만드세요."

" 좋은 솔루션:  단일 객체를 생성하고 정적 변수에 저장합니다. 클래스의 두 번째 객체 생성을 방지합니다. 예를 들면 다음과 같습니다."

class Sun
{
 private static Sun instance;
 public static Sun getInstance()
 {
  if (instance == null)
  instance = new Sun();

  return instance;
 }

 private Sun()
 {
 }
}
그것이 어떻게 불려지는가
Sun sun = Sun.getInstance();

"간단 해."

"먼저 우리는 생성자를 비공개로 만듭니다. 이제 생성자는 우리 클래스 내부에서만 호출할 수 있습니다. Sun 클래스의 메서드 내를 제외한 모든 곳에서 Sun 개체 생성을 차단했습니다."

"둘째, 이 클래스의 개체는 getInstance() 메서드를 호출해야만 얻을 수 있습니다. 이 메서드는 Sun 개체를 만들 수 있는 유일한 메서드일 뿐만 아니라 그러한 개체가 하나만 있는지 확인합니다."

"알겠어요."

""이제 정확히 어떻게 해야 할까요?"라고 생각할 때 패턴은 "이것을 시도해 볼 수 있습니다. 이것이 최고의 솔루션 중 하나입니다."라고 말합니다.

"고맙습니다. 이제 상황이 명확해지기 시작했습니다."

" 여기에서 이 패턴에 대해 읽을 수도 있습니다  ."

공장 패턴.

디자인 패턴: 싱글톤, 팩토리, 팩토리 메소드, 추상 팩토리 - 2

"프로그래머가 매우 자주 직면하는 상황은 다음과 같습니다. 일부 기본 클래스와 많은 하위 클래스가 있습니다. 예를 들어 게임 캐릭터 클래스(GamePerson)와 이를 상속하는 다른 모든 캐릭터에 대한 클래스가 있습니다."

"다음 클래스가 있다고 가정해 보겠습니다."

abstract class GamePerson
{
}

class Warrior extends GamePerson
{
}

class Mag extends GamePerson
{
}

class Troll extends GamePerson
{
}

class Elf extends GamePerson
{
}

"문제는 이러한 클래스의 개체 생성을 유연하고 편리하게 관리하는 방법입니다."

"이 문제가 터무니없어 보인다면 게임에서 수십 개의 검과 방패, 수백 개의 마법 주문, 수천 마리의 몬스터를 만들어야 한다고 상상해보세요. 여기서 객체 생성에 대한 편리한 접근 없이는 할 수 없습니다. "

" 팩토리 패턴은 좋은 솔루션을 제공합니다."

"먼저 값이 다양한 클래스에 해당하는 열거형을 만들어야 합니다."

"둘째, 열거형 값을 기반으로 객체를 생성하는 정적 메서드가 있는 특수 팩토리 클래스를 생성합니다."

"예를 들어:"

public enum PersonType
{
 UNKNOWN,
 WARRIOR,
 MAG,
 TROLL,
 ELF,
}

public class PersonFactory
{
 public static GamePerson createPerson(PersonType personType)
 {
  switch(personType)
  {
   WARRIOR:
   return new Warrior();
   MAG:
   return new Mag();
   TROLL:
   return new Troll();
   ELF:
   return new Elf();
   default:
   throw new GameException();
  }
 }
}
그것이 어떻게 불려지는가
GamePerson person = PersonFactory.createPerson(PersonType.MAG);

"즉, 개체 생성을 관리하기 위해 특수 클래스를 만든 것입니까?"

"네."

"그래서 이것은 어떤 이점을 제공합니까?"

"첫째, 이 클래스에서는 개체를 필요한 데이터로 초기화할 수 있습니다."

"둘째, 궁극적으로 원하는 개체를 생성하기 위해 원하는 만큼 메서드 간에 필요한 enum 값을 전달할 수 있습니다."

"셋째, enum 필드의 수는 클래스의 수와 일치할 필요가 없습니다. 문자의 유형은 많지만 클래스는 적을 수 있습니다."

"예를 들어 Mag & Warrior는 하나의 클래스(Human)를 사용할 수 있지만 강도와 마법 속성이 다릅니다(생성자 인수)."

"다음과 같이 보일 수 있습니다(명확성을 위해 다크 엘프도 추가했습니다)."

public enum PersonType
{
 UNKNOWN,
 WARRIOR,
 MAG,
 TROLL,
 ELF,
 DARK_ELF
}

public class PersonFactory
{
 public static GamePerson createPerson(PersonType personType)
 {
  switch(personType)
  {
   WARRIOR:
   return new Human(10, 0); // Strength, magic
   MAG:
   return new Human(0, 10); // Strength, magic
   TROLL:
   OGR:
   return new Troll();
   ELF:
   return new Elf(true); // true – good, false – evil
   DARK_ELF:
   return new Elf(false); // true – good, false – evil
   default:
   throw new GameException();
  }
 }
}
그것이 어떻게 불려지는가
GamePerson person = PersonFactory.createPerson(PersonType.MAG);

"위의 예에서는 3개의 클래스만 사용하여 6개의 서로 다른 유형의 개체를 만들었습니다. 이것은 매우 편리합니다. 게다가 이 모든 논리가 하나의 클래스와 하나의 메서드에 집중되어 있습니다."

"이제 Ogre를 위한 별도의 클래스를 만들기로 결정했다고 가정해 보겠습니다. 애플리케이션의 절반이 아니라 여기에서 코드 몇 줄만 변경하면 됩니다."

"동의합니다. 좋은 해결책입니다."

"그리고 그것이 내가 말하는 것입니다. 디자인 패턴은 좋은 솔루션의 모음입니다."

"또한 어디에 사용하는지 알고 싶습니다…"

"네. 동의합니다. 바로 이해하지 못할 것입니다. 그래도 모르고 할 수 없는 것보다 알면서도 할 수 없는 것이 낫습니다. 이 패턴에 대한 또 다른 유용한 링크가 있습니다: Factory Pattern "

"오 감사."

" 추상 공장 패턴."

"때때로 개체가 많을 때 공장을 위한 공장을 만드는 아이디어가 떠오를 수 있습니다. 이러한 공장을 추상 공장 이라고 합니다 ."

"어디에 이게 필요하겠어?!"

"동일한 개체 그룹이 여러 개 있다고 가정합니다. 예를 들어 설명하기가 더 쉽습니다."

"이제 게임에 인간, 엘프, 악마의 세 종족이 있다고 가정해 보겠습니다. 그리고 균형을 위해 각 종족에는 전사, 궁수, 마법사가 있습니다. 플레이어는 자신이 플레이하는 종족에 속한 개체만 만들 수 있습니다. 게임에서. 코드에서는 다음과 같이 표시됩니다."

병사 계급 선언
class Warrior
{
}
class Archer
{
}
class Mag
{
}
인간
class HumanWarrior extends Warrior
{
}

class HumanArcher extends Archer
{
}

class HumanMag extends Mag
{
}
엘프
class ElfWarrior extends Warrior
{
}

class ElfArcher extends Archer
{
}

class ElfMag extends Mag
{
}
악마
class DaemonWarrior extends Warrior
{
}

class DaemonArcher extends Archer
{
}

class DaemonMag extends Mag
{
}

이제 인종을 만들거나 군대라고 부를 수도 있습니다.

군대
abstract class Army
{
 public Warrior createWarrior();
 public Archer createArcher();
 public Mag createMag();
}
인간 군대
class HumanArmy extends Army
{
 public Warrior createWarrior()
 {
  return new HumanWarrior();
 }
 public Archer createArcher()
 {
  return new HumanArcher();
 }
 public Mag createMag()
 {
  return new HumanMag();
 }
}
엘프 군대
class ElfArmy extends Army
{
 public Warrior createWarrior()
 {
  return new ElfWarrior();
 }
 public Archer createArcher()
 {
  return new ElfArcher();
 }
 public Mag createMag()
 {
  return new ElfMag();
 }
}
악마의 군대
class DaemonArmy extends Army
{
 public Warrior createWarrior()
 {
  return new DaemonWarrior();
 }
 public Archer createArcher()
 {
  return new DaemonArcher();
 }
 public Mag createMag()
 {
  return new DaemonMag();
 }
}

"근데 이거 어떻게 써요?"

"프로그램의 어느 곳에서나 육군, 전사, 궁수 및 마법사 클래스를 사용할 수 있으며 원하는 육군 하위 클래스의 개체를 전달하기만 하면 필요한 개체를 만들 수 있습니다."

"예를 들어:"

Army humans = new HumanArmy();
Army daemons = new DaemonArmy();

Army winner = FightSimulator.simulate(humans, daemons);

"위의 예에서 서로 다른 종족(군대) 간의 전투를 시뮬레이션하는 클래스가 있습니다. 두 개의 군대 개체를 전달하기만 하면 됩니다. 클래스 자체는 이를 사용하여 다양한 군대를 생성하고 승자를 식별하기 위해 그들 간의 가상 전투를 수행합니다. ."

"그렇군요. 감사합니다. 정말 흥미로운 접근법입니다."

"무슨 말을 하든 좋은 해결책입니다."

"네."

"여기 주제에 대한 또 다른 좋은 링크가 있습니다:  추상 팩토리 패턴 "