디자인 패턴

2017. 6. 5. 16:42기술/디자인 패턴

반응형

디자인 패턴이란 반복되는 설계를 재사용시 편리하게 할 수 있도록 한 설계도라고 생각합니다.

대략적으로 디자인 패턴 23가지에 대해서 알아보겠습니다.

 

실제 게임 개발에서 개발일정상 설계를 꼼꼼하게 못하는 경우도 있고

시간이 좀 남으면 설계와 디자인패턴을 살펴보곤 합니다.

 

디자인 패턴의 다양한 활용에 대해서 연구중입니다.

링크만 두고 연구 내용은 비공개로 전환합니다.

 

디자인 패턴

1. 추상 팩토리 패턴 (Abstract Factory Pattern)

 다양한 객체를 조합해서 하나의 객체를 생성할 수 있습니다. 

 

2. 상태 패턴 (State Pattern)

 객체의 상태를 변경할 때 사용합니다.

 

3. 컴포짓 패턴 (Composite Pattern)

 일괄처리시 사용하면 좋을것 같습니다. 예제가 정말 좋은거 같습니다. 유닛 1번, 2번 부대지정!

 

4. 데코레이터 패턴 (Decorator Pattern)

 기존 클래스를 유지하면서 새로운 개념의 클래스를 만들어내야 할 때 사용하면 좋을것 같습니다. 예를 들어, 그냥 커피가 카라멜 마끼아또가 된다는 것이 요점입니다. 다만, 너무 많이 사용하게 되면 설계가 다소 난잡해 지는 경향이 있습니다. 게임에서 상점 패키지 상품같은것을 구성할 때 사용해보아야 하겠습니다.

 

5. 중재자 패턴 (Mediator Pattern)

 서로 다른 클래스에 연관관계를 모아 사용하면 좋은 패턴입니다. 예를 들어 UIMediator가 있습니다.

 

6. 옵저버 패턴 (Observer Pattern)

 한 클래스에 다른 클래스를 등록(Register)하고 해제(Unregister)하며 특정 이벤트가 있을 때 NotifyObservers()를 해서 함수를 동작시키는 패턴입니다. RPG 게임에서 부하들을 소환하거나 데리고 다니는 어떤 몬스터가 있다고 한다면 부하들을 모두 한곳으로 집합 시키려고 할 때 옵저버 패턴을 사용하면 좋을것 같습니다. 외에도 잘 생각해서 다양한 곳에 유용하게 사용할 수 있겠습니다.

 컴포짓 패턴과 무엇이 다른지 조금 더 생각해봐야겠습니다. ^^;

 

7. 싱글턴 패턴 (Singleton Pattern)

 워낙 많은 사람들이 사용하고 있는 싱글턴 패턴입니다. 저는 스태틱 클래스라고 보거나 스태틱 함수의 개념이라고 생각하고 있습니다. 이 패턴의 단점으로는 쓸데 없이 너무 많은 것을 싱글턴으로 구현하면 설계가 난잡해진 다는 것이고 정말 적재 적소에 프로젝트에서 꼭 하나만 필요한 객체를 싱글턴으로 만들어줘야 할것 같습니다.

 저는 싱글턴 패턴의 사용을 최소화 해야 한다고 생각합니다.

 

8. 프록시 패턴 (Proxy Pattern)

 어떠한 함수 수행을 하는 대리 클래스를 만듭니다. 간단한 예로 interface Network를 만들어 두고 Connection이라는 함수를 만듭니다. Network에서 상속받은 두 ProxyNetwork, RealNetwork 클래스가 있고 ProxyNetwork에서는 서버에 연결이 되면 RealNetwork의 Connection 함수를 호출해 줍니다. 객체를 생성할때, Network network = new ProxyNetwork() network.Connection() 하면 연결이 됩니다.

 이렇게 어떤 수행을 하는데 있어서 대리자 클래스를 만드는 패턴을 프록시 패턴이라고 합니다. 한 프로그래머가 ProxyNetwork를 만들어서 Connection을 호출해 주고 다른 프로그래머가 RealNetwork의 Connection을 구현해서 팀워크 프로그래밍에 활용하면 좋을거 같습니다.

 

 프록시 패턴에 대해 잘 생각해 보다가 다음 아이디어를 생각해 냈습니다. 

 8-1. 소환사가 있고 소환물들이 있을 때, 소환사가 소환물 공격 스킬 버튼을 누른다. 그때 대리자인 모든 소환물들의 AI가 적을 찾아서 공격한다.

 8-2. 또한 주인이 있고 애완동물이 있다. 주인이 적을 잡을 때마다 경험치가 올라간다. 이 때 애완동물이 주인을 대신하여 골드를 찾아서 획득한다.

 이렇게 대리자를 사용하여 무언가 대신 처리하고 싶을 때 사용하면 좋을 패턴인거 같습니다.

 

9. 프로토타입 패턴 (Prototype Pattern)

 위키백과에 설명이 잘 되어 있는데요, "new 키워드 대신에 clone()를 쓴다." 라고 나와 있습니다. 예전에 맵툴을 만들 때, 오브젝트 팔레트라는 클래스를 만들고 여기에는 이미 생성되어진 다양한 오브젝트들이 존재했습니다. 그리고 팔레트에서 오브젝트를 찍어서 맵에 배치할 때, 객체는 새로 생성이 되지만 기존 객체를 clone()해서 사용했었고 메쉬 오브젝트는 공유하며 Transform으로 여러군데에 출력해 주었습니다. 그러니까 객체와 Transform Matrix는 여러개인데 메쉬는 하나이다라는 것이죠.

 

 

10. 빌더 패턴 (Builder Pattern)

 요점은 "동일한 생성 절차"입니다. 예를 들어, 스테이지 팩토리가 있다고 했을 때 맵 생성 -> 캐릭터 생성 -> 카메라 설정 이라는 생성 절차가 있습니다. 만약 맵을 생성하기 전에 캐릭터를 생성하게 되면 캐릭터가 맵 위에 서있을 수 없게 되며 캐릭터 생성 보다 카메라 설정을 먼저 해 버리면 기준 위치를 알 수가 없게 됩니다. 이렇게 생성 절차가 필요할 때 빌더 패턴을 사용합니다. 

 추상 팩토리와 다른점은 추상 팩토리는 생성을 담당하고 빌더는 설정(Setting)을 담당합니다.

 

11. 팩토리 메서드 패턴 (Factory Method Pattern)

 추상 팩토리 패턴은 다소 복잡하고 큰 객체를 생성해 낼 때 사용한다면 팩토리 메서드 패턴은 객체의 종류에 따라 간단하게 하나의 객체를 만들어 낼 때 사용하는 공용함수입니다.

 

12. 아답터 패턴 (Adapter Pattern)

 예를 들어, 서버 엔진이 자체엔진, 프라우드넷 또는 텐센트의 G-Cloud 라이브러리가 있다고 합시다. VenderClass가 이러한 서버 라이브러리 이고 클라이언트에서 개발한 코드가 Your Existing System이라고 하면 그 중간에 Adapter를 두어서 프라우드넷을 사용하던 네트워크를 텐센트의 G-Cloud로 변환할 수 있는 패턴입니다.

 TCP로 캐릭터가 Attack()함수를 실행했을 때 아답터를 통해 서버에 패킷을 보내면 될 것입니다. 아답터를 만들어 놓으면 텐센트 서버쪽은 중국 개발자들이 만들어도 되겠습니다.

 

13. 브릿지 패턴 (Bridge Pattern)

 기능과 구현을 별도의 인터페이스(Interface)로 정의해서 서로를 분리하는 방법입니다. 이 패턴을 사용하면 하나의 동작에 여러가지 함수를 사용할 수 있습니다. 일단은 UseEquipment()에서 무기 변경시 호출하는 함수를 달리해 줄 수 있겠습니다.

 

14. 퍼사드 패턴 (Facade Pattern)

 Facade는 표면이라는 뜻인데 이런 표면 클래스를 하나 만들어서 다른 객체들을 참조해서 한꺼번에 관리할 수 있습니다. 예를 들어, 이미 Computer, Moniter, Speaker 클래스가 있는데 한꺼번에 On(), Off()를 해주고 싶습니다. 이럴 때 퍼사드 패턴을 사용할 수 있습니다. 또한 Computer, Moniter만 켜고 싶을 때도 OnMoniter() 함수를 만든 다음 컴퓨터와 모니터만 켜주면 됩니다. 응용할만한 것을 더 생각해 봐야겠습니다.

 Player와 Camera가 있을 때 PlayerFacade를 만들어서 Player와 Camera가 함께 이동하는 것을 만들어 줄 수도 있겠습니다.

 UI를 켜고 끌 때에도 유용하게 사용할 수 있겠습니다. UI에서 어떤 창을 띄울 때 다른것들은 꺼야하는 상황이 있습니다. 퍼사드 패턴으로 따로 관리하면 켜고 끄는것을 관리할 수 있겠습니다.

 

15. 플라이웨이트 패턴 (Flyweight Pattern)

 요점은 "이미 있는 객체는 공유해서 사용한다." 입니다. 예를 들어, 몬스터를 여럿 만들어 줄 때, 고정된 Stats값이 있을 것입니다. 외에 HP처럼 변하는 값이 있을 것입니다. 고정값 변하는 값을 분리해서 고정값 객체를 공유해서 사용한다면 메모리 절약을 할 수 있습니다.

 아주 작은 메모리 절약이라고 생각할수도 있겠습니다만 메모리를 적게 먹으면 할 수 있는 것들이 늘어납니다. 다른 객체를 생성할 수 있는 여유가 조금이라도 더 생기게 되니까요.

 엑셀에서 읽어온 데이터 클래스는 그냥 참조 해서 사용하고 새로 메모리 할당을 해서 대입해서 사용하면 안됄거 같습니다. 이 패턴은 개체수가 많아질 수록 효과를 발휘하는 패턴입니다.

 

16. 책임 연쇄 패턴 (Chain of Responsibility Pattern)

 이름 그데로 객체들이 하나의 사슬을 이루는 링크드 리스트 형태입니다. 설계 구조가 체인 형식일 때 한 번쯤 생각해 봐야하는 패턴이라고 생각합니다. 가장 적합한 예가 문의전화가 왔을 때 해결할 수 있으면 해결해주고 그렇지 않으면 책임을 전가하는 방법을 구현할 때 사용하면 좋을것 같습니다. 다른 예도 더 생각해 봐야겠습니다.

 스킬 예약 시스템을 구현한다고 했을 때, 3개의 연속 스킬을 .SetNext로 연결해 놓고 "다음 스킬이 사용가능 한가?"를 물은 다음 사용가능하면 사용하고 그렇지 않으면 처음으로 돌아가는 방법을 구현할 때 사용해 보아도 좋을거 같습니다. (또는 캐릭터의 연속공격)

 체인 라이트닝이라는 스킬을 구현할 때에도 사용할 수 있을거 같습니다. 다음 몬스터에게 라이트닝이 도달 가능한가? 그렇지 않았을 때 처리 (몬스터가 1마리 뿐일경우)

 

17. 커맨드 패턴 (Command Pattern)

 프로그램에는 많은 명령어가 존재하는데 그 명령어를 하나의 클래스로 만들면 다양한 것을 할 수 있을거 같습니다. 예를 들어, ICommand 인터페이스를 상속받은 OpenUICommand, CloseUICommand를 만듭니다. 그리고 UI에서 Open, Close 버튼을 클릭했을 때의 각각 함수를 연결해 주면 됩니다. 그럼 OpenUICommand에서 퍼사드 패턴을 사용해서 특정 객체들을 켜주고 어떤 UI가 켜졌는지 Stack에 한번 쌓은 다음 CloseUICommand에서 특정 객체들을 꺼주고 Stack에서 빼내는 기능외 필요한 다른 기능들을 추가해 주면 좋을거 같습니다.

 발동자(Invoker), 수신자(Receiver), 명령(Command), 클라이언트(Client)에 대해서 잘 알아야겠습니다. (발신자가 Switch 수신자가 Light)

 사실 맵툴같은 툴에 사용하면 더욱 유용하겠네요. Undo, Redo 기능을 구현할때 말입니다.

 

18. 인터프리터 패턴 (Interpreter Pattern)

 채팅창에 Show me the money라든가 /귓속말 /춤 등을 입력했을 때 사용하면 좋은 패턴인거 같습니다.

 

19. 이터레이터 패턴 (Iterator Pattern)

 C# Dictionary에는 이미 Enumerator라고 있습니다. MoveNext하면서 해당 이터레이터의 키와 값에 접근할 수 있습니다. MoveNext 로직에 수정이 필요할 경우 또는 다른 이유로 이를 굳이 구현해 주어야 할 때, 반복자 이터레이터를 사용하면 될거 같습니다. 

 

20. 메멘토 패턴 (Memento Pattern)

 객체의 상태 정보를 저장 및 복원(Rollback, Recovery)하는 패턴입니다. UI Open, Close할 때 일단 메멘토 패턴을 사용해봐야겠습니다. (응용예)

 

21. 스트래티지 패턴 (Strategy Pattern)

 몬스터의 AI 알고리즘을 변경해주고 싶을때 참고할만한 패턴? 알고리즘군을 정의하고 각각캡슐화하여 교환할 수 있는 패턴이라고 합니다.

 

22. 템플릿 메서드 패턴 (Template Method Pattern)

 "여러 클래스에서 공통되는 사항은 상위 클래스에서 구현하고, 각가의 상세 부분은 하위 클래스에서 구현한다." 

 프레임워크를 짤 때 보통 사용하며 꼭 이 패턴을 모르고 있더라도 이렇게 설계하고 코드를 작성하는 일이 많았습니다.

 "설계하고 코드를 작성해 보니 그게 템플릿 메서드 패턴이었네?"라고 할 수 있을 정도로 자주 사용하던 패턴입니다.

 

23. 비지터 패턴 (Visitor Pattern)

 이미 구현이 되어 있는데 추가 기능을 넣고자 할 때, 잠시 방문하면 좋은 패턴입니다. VisitorSomething 클래스를 만들고 visit 함수를 만든다음 추가 기능이 필요한 클래스에 함수를 추가하고 Visitor를 매개 변수로 넘겨주어서 방문하여 처리하게 합니다.

 

 

 

 

 

 

반응형

'기술 > 디자인 패턴' 카테고리의 다른 글

캐릭터 테이블 데이터 아답터 패턴 활용  (0) 2021.04.09