JAVA

[디자인패턴] Factory Method

gom1n 2022. 3. 21. 06:52

FactoryMethod

 

4-1) 예제 프로그램에서는 IDCard 클래스의 생성자는 public이 아닙니다. 이것은 무엇을 나타내고 있습니까?

public class IDCard extends Product {
	...
	IDCard(String owner) {
		...
		this.owner = owner;
	}
	...
}

위와 같이 앞에 아무런 접근제어자가 붙어있지 않은 경우라면, 디폴트로 package 접근이라고 볼 수 있습니다.

package : 같은 패키지에 선언되어있는 다른 클래스까지만 접근이 허용된다.

따라서 IDCard의 인스턴스는 패키지 외부로부터 보호되어있기 때문에, 같은 패키지에 있는 IDCardFactory를 경유해야합니다. → 유지보수성

 

+) 만약 생성자가 public이라면?

//기존 Main
Factory factory = new IDCardFactory(); 
Product card1 = factory.create("홍길동");

//만약 public이라면?
IDCard idcard = new IDCard("홍길동");

위와 같이 new를 사용해서 객체를 생성하게 되는데, 만약 이렇게 될 시 IDCard 클래스에 변경사항이 생긴다면 바꿔야할 코드가 늘어납니다.

→ 유지보수에 적합하지 않습니다.

 

 

4-2) 예제 프로그램의 IDCard 클래스에 카드의 인증번호를 붙이고, IDCardFactory 클래스가 인증번호와 소지자의 대응표를 갖도록 수정해보십시오.

→ 문제의도 : IDCard클래스와 IDCardFactory클래스를 수정해도 프레임워크 쪽과 Main클래스의 소스코드를 수정할 필요가 전혀 없다는 점!

 

정답코드 😎

더보기

IDCard.java

package idcard;
import framework.*;

public class IDCard extends Product {
    private String owner;
    private int serial;
    IDCard(String owner, int serial) {
        System.out.println(owner + "(" + serial + ")" + "의 카드를 만듭니다.");
        this.owner = owner;
        this.serial = serial;
    }
    public void use() {
        System.out.println(owner + "(" + serial + ")" + "의 카드를 사용합니다.");
    }
    public String getOwner() {
        return owner;
    }
    public int getSerial() {
        return serial;
    }
}

 

IDFactory.java

package idcard;
import framework.*;
import java.util.*;

public class IDCardFactory extends Factory {
		//HashMap 사용: serial번호(Integer), 이름(String)
    private HashMap<Integer, String> database = new HashMap<Integer, String>();
    private int serial = 100;
		//synchronized
    protected synchronized Product createProduct(String owner) {
        return new IDCard(owner, serial++);
    }
    protected void registerProduct(Product product) {
        IDCard card = (IDCard)product;
        database.put(new Integer(card.getSerial()), card.getOwner());
    }
    public HashMap<Integer, String> getDatabase() {
        return database;
    }
}

 

+ HashMap

HashMap은 Map 인터페이스를 구현하고 있는 대표적인 클래스입니다. 그리고 Map의 구조인 key-value쌍으로 구성되어 있습니다.

그리고 Map의 대표적인 특징은 하나의 key는 정확히 하나의 value만 가질 수 있다는 것입니다.

public class HashMap<K,V> extends AbstractMap<K,V>
    implements Map<K,V>, Cloneable, Serializable {
}

여기에서 자세히 확인

 

+ Synchronized?

- 교수님이 강의에서 예로 설명해주신 은행계좌에 100만원 넣기

- 스레드간 동기화가 되지 않은 상태에서 멀티스레드 프로그램을 돌리면, data의 안정성신뢰성을 보장할 수 없습니다.

- 따라서 자바에서는 synchronized 키워드를 제공 : 여러개의 스레드가 한 개의 자원을 사용하고자 할 때, 현재 데이터를 사용하고 있는 해당 스레드를 제외하고 나머지 스레드들은 데이터에 접근할 수 없도록 막는 개념

// method에서의 synchronized 사용
public synchronized void method(){ ... }

//class에서의 synchronized 사용
private Object obj = new Object();
public void Class(){ 
	synchronized(obj){ ... }
	}

 

 

 

4-3) Product 클래스의 하위 클래스에서는 생성자에서 반드시 ‘제품의 이름'을 인수로 부여하도록 다음과 같이 Product 클래스를 정의했습니다. 그러나 컴파일할 때 에러가 발생했습니다. 이유가 무엇입니까?

public abstract class Product {
	public abstract Product(String name);
	public abstract void use();
}

생성자는 상속이 가능한가?

→ 생성자는 상속이 되지 않습니다. 대신 자식 클래스로 인스턴스를 생성할 때 자동으로 상위클래스의 생성자를 호출하게 됩니다.

따라서 abstract한 생성자는 의미가 없습니다.

위와 같은 경우에서는 이름을 인수로 부여하기 위해선 생성자가 아닌, 메소드를 별도로 선언해야합니다.


발표자료

https://elfin-roadway-384.notion.site/3-24-FactoryMethod-Singleton-5782f8e834f1482fa3c932914496cb94

 

3/24 디자인패턴 - FactoryMethod, Singleton

4장 FactoryMethod

elfin-roadway-384.notion.site