널 객체 패턴(Null Object Pattern)은 가능한 한 null 검사를 피하면서 깔끔하고 안전한 코드를 작성할 수 있도록 도와주는 디자인 패턴입니다. 이 패턴을 활용하면 호출부(caller)는 자신이 다루는 객체가 실제 객체인지, 아니면 아무 동작도 수행하지 않는 널 객체인지 일일이 신경 쓸 필요가 없습니다.
다만 모든 상황에서 널 객체 패턴을 적용할 수 있는 것은 아닙니다. 경우에 따라서는 null 참조를 그대로 반환하고 null 검사를 수행하는 편이 더 적절할 수도 있습니다. 따라서 이 패턴은 "null 처리 로직이 반복적으로 등장하는 지점"에 선택적으로 적용하는 것이 좋습니다.
예제 코드
아래 예제는 C#에서 널 객체 패턴을 싱글톤(Singleton) 방식으로 구현한 코드입니다. 이름에 해당하는 도형이 있으면 실제 객체를 반환하고, 없으면 아무 작업도 하지 않는 NullShape 객체를 반환합니다.
static class Program{
static void Main(string[] args){
Console.ReadLine();
}
public static IShape GetMobileByName(string mobileName){
IShape mobile = NullShape.Instance;
switch (mobileName){
case "square":
mobile = new Square();
break;
case "rectangle":
mobile = new Rectangle();
break;
}
return mobile;
}
}
public interface IShape {
void Draw();
}
public class Square : IShape {
public void Draw() {
throw new NotImplementedException();
}
}
public class Rectangle : IShape {
public void Draw() {
throw new NotImplementedException();
}
}
public class NullShape : IShape {
private static NullShape _instance;
private NullShape(){ }
public static NullShape Instance {
get {
if (_instance == null)
return new NullShape();
return _instance;
}
}
public void Draw() {
}
}코드 구조 설명
1. IShape 인터페이스
모든 도형 객체가 반드시 구현해야 할 Draw() 메서드를 정의합니다. 실제 객체와 널 객체가 동일한 계약(contract)을 따르기 때문에 클라이언트 코드는 두 객체를 구분할 필요가 없습니다.
2. 실제 구현 클래스 (Square, Rectangle)
Square와 Rectangle은 IShape를 구현하는 실제 도형 클래스입니다. 여기서는 예시를 위해 NotImplementedException을 던지도록 작성되었으며, 실제 프로젝트에서는 도형을 그리는 로직이 들어갑니다.
3. 널 객체 (NullShape)
NullShape는 어떤 동작도 수행하지 않는 널 객체입니다. 주요 특징은 다음과 같습니다.
- private 생성자: 외부에서 임의로 인스턴스를 생성하지 못하도록 막습니다.
- 정적 Instance 속성: 싱글톤 패턴처럼 단일 인스턴스를 재사용하여 불필요한 객체 생성을 방지합니다.
- 빈 Draw() 메서드: 호출되더라도 예외를 던지거나 오류를 발생시키지 않고 조용히 아무 일도 하지 않습니다.
패턴 적용의 장점
- 호출부에서
if (obj == null)같은 반복적인 null 검사 코드를 제거할 수 있습니다. - NullPointerException 유형의 런타임 오류 발생 가능성을 줄여 코드 안정성이 높아집니다.
- null 여부에 따른 분기 로직이 사라져 코드의 가독성과 유지보수성이 향상됩니다.
GetMobileByName 메서드처럼 기본값으로 NullShape.Instance를 설정해 두면, 조건에 맞는 도형이 없을 때도 호출부는 안심하고 Draw()를 호출할 수 있습니다. 이것이 바로 널 객체 패턴의 핵심 아이디어입니다.