일반 생성자로 객체를 생성할때 발생할 수 있는 문제점
1. class 의 생성자는 동일한 signature 별로 하나의 생성자만 가질수 있다.
(signature : 매개변수의 구성을 뜻하며 자료형, 갯수, 순서에 따라 달라진다.)
2.다른 초기화 기능이나 목적을 가진 객체를 생성하기 위해 생성자 매개변수의 순서를 바꾸는 방법으로 생성자를 overloading 한다.
3. 이렇게 만들어진 생성자를 사용하는 코드를 작성하려는 사람은 코드나 api 설명을 참조하지 않고서는 생성자가 만드려는 객체가 어떤 초기화 기능을 하는지 파악하지 못한다.
아래와 같은 class 가 있을때
public class Person {
private int age;
private int year;
private String name;
// 일반 생일자
public Person(int age, int year, String name) {
this.age = age;
this.year = year;
this.name = name;
}
// 빠른 생일자
public Person(String name, int age, int year) {
this.name = name;
this.age = age + 1;
this.year = year;
}
}
빠른 생일자 객체와 일반 생일자 객체를 생성하려고 할때 아래와 같은 코드로 생성할 수 있다.
class PersonMain {
public static void main(String[] args) {
Person man = new Person(21, 1990, "홍길동");
Person earlyBirthMan = new Person(“빠른 홍길동", 20, 1991);
}
}
하지만 Person class 코드를 보지 않고서는 빠른생일자와 일반생일자를 구별하여 객체를 생성할 수 없다.
(장점 1) 반면 정적 팩터리 메서드는 생성자의 class 명이 아닌 메소드 명을 명명할수 있다.
팩터리 메서드의 이름으로 생성하는 객체의 특성을 나타낼수도 있다.
또 같은 signaure 를 가진 생성자는 오로지 하나 이지만 팩터리 메서드로는 메서드명만 달리하면 그 제한이 없다.
따라서 같은 시그너처를 갖는 생성자를 여러개 정의할 필요가 있을때와
생성자마다 생성할 객체의 특성을 나타낼 필요가 있을때
정적 팩터리 메서드로 생성자를 대신하여 객체를 생성하는 것이 좋다.
아래는 정적 팩토리 메서드를 사용한 수정한 코드이다.
class ImprovedPerson {
private int age;
private int year;
private String name;
private ImprovedPerson(int age, int year, String name){
this.age = age;
this.year = year;
this.name = name;
}
// 일반생일자
public static ImprovedPerson getPerson(int age, int year, String name) {
return new ImprovedPerson(age, year, name);
}
// 빠른생일자
public static ImprovedPerson getEarlyBirthPerson(String name, int age, int year) {
return new ImprovedPerson(age + 1, year, name);
}
}
class PersonMain {(장점 2) 또한 생성자와는 달리 호출할 때마다 새로운 객체를 생성할 필요가 없다.
public static void main(String[] args) {
ImprovedPerson man = ImprovedPerson.getPerson(21, 1990, "홍길동");
ImprovedPerson earlyBirthMan = ImprovedPerson.getEarlyBirthPerson(20, 1991, "빠른 홍길동");
}
}
싱글턴 뿐만 아니라 몇몇의 만들어진 객체를 pool 형태로 캐시 해놓고 재사용도 가능하다.
class Sun {
private static Sun sun = new Sun();
// 생성자로 객체 생성 불가능하도록
private Sun(){}
// 항상 같은 객체 반환
public static Sun getInstance() {
return sun;
}
}
class Star {
// Sun class 에서 extends 하기 때문에 private 선언 할 수 없음
Star(){}
public static Star getSun() {
return Sun.getInstance();
}
}
class Sun extends Star {
private static Sun sun = new Sun();
// 생성자로 객체 생성 불가능하도록
private Sun(){
}
// 항상 같은 객체 반환
public static Sun getInstance() {
return sun;
}
}
interface Star {)
void hello();
}
public class StarBuilder {
private StarBuilder(){}
public static Star getSun() {
return Sun.getInstance();
}
public static Star getMoon() {
return Moon.getInstance();
}
}
class Sun implements Star {
private static Sun sun = new Sun();
// 생성자로 객체 생성 불가능하도록
private Sun() {
}
// 항상 같은 객체 반환
public static Sun getInstance() {
return sun;
}
@Override
public void hello() {
System.out.println("hi sun");
}
}
class Moon implements Star {
private static Moon moon = new Moon();
// 생성자로 객체 생성 불가능하도록
private Moon() {
}
// 항상 같은 객체 반환
public static Moon getInstance() {
return moon;
}
@Override
public void hello() {
System.out.println("hi moon");
}
}
public class Client {
public static void main(String[] args) {
Star s = StarBuilder.getSun();
Star m = StarBuilder.getMoon();
s.hello();
m.hello();
}
}
public static <E> Set<E> newSetFromMap(Map<E, Boolean> var0) {
return new Collections.SetFromMap(var0);
}
private static class SetFromMap<E> extends AbstractSet<E> implements Set<E>, Serializable {
private final Map<E, Boolean> m;
private transient Set<E> s;
private static final long serialVersionUID = 2454657854757543876L;
SetFromMap(Map<E, Boolean> var1) {
if(!var1.isEmpty()) {
throw new IllegalArgumentException("Map is non-empty");
} else {
this.m = var1;
this.s = var1.keySet();
}
}
………………
}
public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> var0) {
Enum[] var1 = getUniverse(var0);
if(var1 == null) {
throw new ClassCastException(var0 + " not an enum");
} else {
return (EnumSet)(var1.length <= 64?new RegularEnumSet(var0, var1):new JumboEnumSet(var0, var1));
}
}
public interface Map<K,V> {
Map<String, Integer> m = new HashMap<String, Integer>();이렇게 일반적인 생성시 Map 의 형인자 자료형을 HashMap 생성시에도 작성해줘야 한다.
public static <K, V> HashMap<K, V> newHashMap() {
return new HashMap();
}
Map<String, List<List<List<String>>>> crazyVariable = Maps.newHashMap();
Map<String, List<List<List<String>>>> crazyVariable = new HashMap<>();
댓글 없음:
댓글 쓰기