본문 바로가기

books/effectivejava

객체 생성과 파괴(1)

반응형

생성자 대신 정적 팩토리 메서드를 고려해라

1. 이름을 갖는다.

  • 이름으로 명확하게 어떤 인스턴스를 생성하는지 확인

2. 호출될 때마다 인스턴스를 새로 생성하지 않아도 된다.

public static Boolean valueOf(boolean b) {
    return (b ? Boolean.TRUE : Boolean.FALSE);
}
  • 객체를 새롭게 만들지 않고 미리 만들어둔 인스턴스를 반환
  • 캐싱도 가능

3. 반환타입의 하위타입 반환 가능

public class WidgetFactory {
    public static Widget createWidget() {
        return new ExternalWidget();
    }
}

class ExternalWidget implements Widget {
    @Override
    public void performAction() {
        System.out.println("External widget action");
    }
}

interface Widget {
    void performAction();
}

// 클라이언트 코드
public class Main {
    public static void main(String[] args) {
        Widget widget = WidgetFactory.createWidget();
        widget.performAction();
    }
}

4. 매개변수에 따라 다른 클래스 객체 반환 가능

interface Shape {
    void draw();
}

class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println("Drawing a Circle");
    }
}

class Rectangle implements Shape {
    @Override
    public void draw() {
        System.out.println("Drawing a Rectangle");
    }
}

class Square implements Shape {
    @Override
    public void draw() {
        System.out.println("Drawing a Square");
    }
}

class ShapeFactory {
    // 매개변수에 따라 다른 클래스의 객체를 반환
    public static Shape getShape(String shapeType) {
        if (shapeType == null) {
            return null;
        }
        if (shapeType.equalsIgnoreCase("CIRCLE")) {
            return new Circle();
        } else if (shapeType.equalsIgnoreCase("RECTANGLE")) {
            return new Rectangle();
        } else if (shapeType.equalsIgnoreCase("SQUARE")) {
            return new Square();
        }
        return null;
    }
}

// 클라이언트 코드
public class Main {
    public static void main(String[] args) {
        Shape shape1 = ShapeFactory.getShape("CIRCLE");
        shape1.draw();  // 출력: Drawing a Circle

        Shape shape2 = ShapeFactory.getShape("RECTANGLE");
        shape2.draw();  // 출력: Drawing a Rectangle

        Shape shape3 = ShapeFactory.getShape("SQUARE");
        shape3.draw();  // 출력: Drawing a Square
    }
}
  • 입력 매개변수를 확인하고 매번 새로운 Shape을 생성

5. 정적 메서드를 작성할 때에는 반환할 클래스가 존재하지 않아도 된다.

interface Animal {
    void speak();
}

class Dog implements Animal {
    @Override
    public void speak() {
        System.out.println("Bark");
    }
}

class Cat implements Animal {
    @Override
    public void speak() {
        System.out.println("Meow");
    }
}

class AnimalFactory {
    public static Animal getAnimal(String type) {
        if (type.equalsIgnoreCase("dog")) {
            return new Dog();
        } else if (type.equalsIgnoreCase("cat")) {
            return new Cat();
        } else {
            return null;
        }
    }
}

// 클라이언트 코드
public class Main {
    public static void main(String[] args) {
        Animal animal = AnimalFactory.getAnimal("dog");
        animal.speak();  // 출력: Bark
    }
}
  • 스타틱 메서드 반환 타입은 단순히 animal -> dog, cat 클래스를 몰라도 문제 없음
  • 정적 팩토리 메소드를 통해 반환되는 객체의 타입이 실행 시점에 결정될 수 있으며, 메소드를 정의할 때 구체적인 클래스 타입을 명시하지 않아됨
반응형