C# 객체 지향 디자인 패턴 1
이 글은 얄팍한 코딩사전의 영상을 바탕으로 추가적인 자료를 수집해서 만든 글입니다.
https://www.youtube.com/watch?v=lJES5TQTTWE&t=200s
1. Singleton (싱글턴)
https://jjung9447.tistory.com/29
2. Strategy (전략패턴)
전략 패턴은 일반적으로 컨텍스트(Context) 객체, 전략(Strategy) 객체, 클라이언트(Client) 객체로 구성된다 컨텍스트 객체는 클라이언트로부터 전략 객체를 전달받아 사용하며, 전략 객체는 알고리즘을 구현한다. 클라이언트 객체는 컨텍스트 객체에게 요청을 하고, 컨텍스트 객체는 전략 객체를 이용하여 요청을 처리한다.
전략 패턴을 사용하면, 알고리즘을 변경하고자 할 때 해당 알고리즘을 구현한 전략 객체만 교체하면된다. 또한, 전략 객체를 쉽게 추가할 수 있으므로 확장성이 높아지며, 컨텍스트 객체와 전략 객체가 느슨하게 결합되므로 유지보수가 용이해진다!
// 무기 인터페이스
public interface IWeapon
{
void Attack();
}
// 검 클래스
public class Sword : IWeapon
{
public void Attack()
{
Console.WriteLine("검으로 공격합니다.");
}
}
// 활 클래스
public class Bow : IWeapon
{
public void Attack()
{
Console.WriteLine("활로 공격합니다.");
}
}
// 전략 클래스
public class WeaponStrategy
{
private IWeapon _weapon;
public WeaponStrategy(IWeapon weapon)
{
_weapon = weapon;
}
public void Attack()
{
_weapon.Attack();
}
}
// 캐릭터 클래스
public class Character
{
private WeaponStrategy _weaponStrategy;
public Character(WeaponStrategy weaponStrategy)
{
_weaponStrategy = weaponStrategy;
}
public void Attack()
{
_weaponStrategy.Attack();
}
}
// 사용 예시
static void Main(string[] args)
{
// 검 전략
WeaponStrategy swordStrategy = new WeaponStrategy(new Sword());
Character knight = new Character(swordStrategy);
knight.Attack(); // 검으로 공격합니다.
// 활 전략
WeaponStrategy bowStrategy = new WeaponStrategy(new Bow());
Character archer = new Character(bowStrategy);
archer.Attack(); // 활로 공격합니다.
}
컨텍스트(Context) 객체는 전략(Strategy) 객체를 사용하는 주체 : Character
전략(Strategy) 객체는 컨텍스트 객체에서 사용되는 알고리즘을 나타내는 인터페이스를 구현하는 클래스 : Sword와 Bow 클래스
클라이언트(Client)는 전략 객체를 컨텍스트 객체에게 전달하는 : 위 예제에서는 Main 함수가 클라이언트에 해당합니다.
3. State (상태 패턴)
유한상태 머신이 상태패턴을 사용한 이론이다.
https://jjung9447.tistory.com/28
4. Command (명령패턴)
근본적으로 전략 패턴과 유사한데,, Strategy 패턴과 다른점은 하는 일 자체가 다르다는 것이다.
Bow와 Sword는 근본적으로 공격을 하는 코드기 때문에 동시에 순서대로 일어날 일이 없다. (갑자기 한 메서드 안에 전사의 칼을 사용하다가 활로 갈아낄 일이 있을까,,?)
아래의 코드는 동시에 있을 수 있는. 점프와 공격을 동시에 하는 패턴을 아래와 같이 동시에 사용하는 코드이다.
// 커맨드 인터페이스
public interface ICommand
{
void Execute();
}
// 공격 커맨드 클래스
public class AttackCommand : ICommand
{
private Character _character;
public AttackCommand(Character character)
{
_character = character;
}
public void Execute()
{
_character.Attack();
}
}
// 점프 커맨드 클래스
public class JumpCommand : ICommand
{
private Character _character;
public JumpCommand(Character character)
{
_character = character;
}
public void Execute()
{
_character.Jump();
}
}
// 캐릭터 클래스
public class Character
{
public void Attack()
{
Console.WriteLine("공격합니다.");
}
public void Jump()
{
Console.WriteLine("점프합니다.");
}
}
// 커맨드 클라이언트 클래스
public class CommandClient
{
private List<ICommand> _commandList;
public CommandClient()
{
_commandList = new List<ICommand>();
}
public void AddCommand(ICommand command)
{
_commandList.Add(command);
}
public void ExecuteCommands()
{
foreach (ICommand command in _commandList)
{
command.Execute();
}
}
}
// 예시
static void Main(string[] args)
{
var character = new Character();
var attackCommand = new AttackCommand(character);
var jumpCommand = new JumpCommand(character);
var commandClient = new CommandClient();
commandClient.AddCommand(attackCommand);
commandClient.AddCommand(jumpCommand);
commandClient.ExecuteCommands(); // 공격합니다. 점프합니다.
}
5. Adapter (어댑터 패턴)
Adapter 패턴은 기존 클래스의 인터페이스를 클라이언트에서 사용하고자 하는 다른 인터페이스로 변환하는 패턴이다.
말 그대로 어댑터 역할을 한다. 중간에 하나의 클래스를 두어서 변환할 때 사용한다. 개인적으로 제일 쉬운 패턴인듯.
// 기존 라이브러리의 인터페이스
public interface ILibraryInterface
{
void Request();
}
// 새로운 인터페이스
public interface INewInterface
{
void Execute();
}
// Adapter 클래스
public class Adapter : INewInterface
{
private ILibraryInterface _libraryInterface;
public Adapter(ILibraryInterface libraryInterface)
{
_libraryInterface = libraryInterface;
}
public void Execute()
{
_libraryInterface.Request();
}
}
// 라이브러리 클래스
public class Library : ILibraryInterface
{
public void Request()
{
Console.WriteLine("기존 라이브러리를 사용합니다.");
}
}
// 새로운 클래스
public class NewClass : INewInterface
{
public void Execute()
{
Console.WriteLine("새로운 클래스를 사용합니다.");
}
}
// 클라이언트 클래스
public class Client
{
private INewInterface _newInterface;
public Client(INewInterface newInterface)
{
_newInterface = newInterface;
}
public void Execute()
{
_newInterface.Execute();
}
}
// 예시
static void Main(string[] args)
{
// 기존 라이브러리를 사용하는 경우
var library = new Library();
var adapter = new Adapter(library);
var client = new Client(adapter);
client.Execute(); // 기존 라이브러리를 사용합니다.
// 새로운 클래스를 사용하는 경우
var newClass = new NewClass();
client = new Client(newClass);
client.Execute(); // 새로운 클래스를 사용합니다.
}
6. Proxy (프록시 패턴)
다른 객체에 대한 접근을 제어하기 위해 대리자 역할을 하는 객체를 두는 패턴. 실제 객체와 클라이언트 사이에 프록시 객체를 두어서, 클라이언트가 프록시 객체를 통해 실제 객체에 접근케 한다.
- 원격지의 객체를 로컬에서 사용해야 할 경우
- 객체의 생성이 비용이 많이 들어가는 경우
- 객체의 생성과 소멸을 제어해야 하는 경우
- 객체에 접근할 때 추가적인 로직을 수행해야 하는 경우
예시에서는 유튜브 썸네일을 예로 드셨다. 미리보기에 쓸모가 있을듯.
// Subject 인터페이스
public interface ISubject
{
void Request();
}
// RealSubject 클래스
public class RealSubject : ISubject
{
public void Request()
{
Console.WriteLine("RealSubject: Request 메서드를 호출합니다.");
}
}
// Proxy 클래스
public class Proxy : ISubject
{
private RealSubject _realSubject;
public Proxy()
{
_realSubject = new RealSubject();
}
public void Request()
{
Console.WriteLine("Proxy: Request 메서드를 호출합니다.");
_realSubject.Request();
}
}
// 예시
static void Main(string[] args)
{
ISubject subject = new Proxy();
subject.Request();
}
'게임공부 > 디자인패턴' 카테고리의 다른 글
[디자인패턴] Flyweight Pattern 경량패턴 (0) | 2023.05.18 |
---|---|
객체 지향 설계 5대 원칙 SOLID (1) | 2023.05.14 |
[디자인 패턴] 디자인 패턴 개요 (0) | 2023.05.12 |
Design Patterns - 싱글톤(Singleton) (0) | 2023.04.28 |