1. 예제 프로그램 - 신분증(ID 카드)을 만드는 공장
<Product.java>
package ch04.Sample.framework;
// 구체적인 제품들이 가져야 메소드를 정의한 추상 클래스
public abstract class Product {
public abstract void use();
}
<Factory.java>
package ch04.Sample.framework;
public abstract class Factory {
// 물건 만들고, 등록하는 일을 하는 메소드 (템플릿메소드이다)
public final Product create(String owner) {
Product p = createProduct(owner);
registerProduct(p);
return p;
}
// 하위 클래스(구체적인 공장)에서 구현하는 메소드들
protected abstract Product createProduct(String owner);
protected abstract void registerProduct(Product product);
}
<IDCard.java>
package ch04.Sample.idcard;
import ch04.Sample.framework.*;
public class IDCard extends Product {
private String owner;
// private이나 public 으로 선언되어 있지 않으면,
// 같은 패키지에 속한 클래스들만이 이 생성자를 호출할 수 있다.
IDCard(String owner) {
System.out.println(owner + "의 카드를 만듭니다.");
this.owner = owner;
}
public void use() {
System.out.println(owner + "의 카드를 사용합니다.");
}
public String getOwner() {
return owner;
}
}
<IDCardFactory.java>
package ch04.Sample.idcard;
import ch04.Sample.framework.*;
import java.util.*;
public class IDCardFactory extends Factory {
// Vector는 배열과 비슷하지만 전체 크기가 정해져 있지 않고
// 원소를 추가하면 필요한 경우 크기가 늘어난다.
private Vector owners = new Vector();
// 이 공장의 제품인 IDCard를 생산한다.
protected Product createProduct(String owner) {
return new IDCard(owner);
}
// 생산된 제품의 owner를 등록(추가)한다.
protected void registerProduct(Product product) {
// product 를 IDCard로 형변환해야, getOwner()를 호출할 수 있다.
owners.add(((IDCard)product).getOwner());
}
public Vector getOwners() {
return owners;
}
}
<Main.java>
package ch04.Sample;
import ch04.Sample.framework.*;
import ch04.Sample.idcard.*;
public class Main {
public static void main(String[] args) {
// IDCard( ) 생성자가 public이 아니라, 아래 문장은 오류가 발생한다.
//IDCard card1 = new IDCard("홍길동");
// 공장을 세운다.
Factory factory = new IDCardFactory();
// 공장을 이용해서 제품(IDCard를 생산한다)
Product card1 = factory.create("홍길동");
Product card2 = factory.create("이순신");
Product card3 = factory.create("강감찬");
// 생산된 제품을 사용한다.
card1.use();
card2.use();
card3.use();
}
}
2. 연습 문제 - IDCard 제품 생성시 Serial 번호를 붙인다
<Product.java>
package ch04.A2.framework;
public abstract class Product {
public abstract void use();
}
<Factory.java>
package ch04.A2.framework;
public abstract class Factory {
public final Product create(String owner) {
Product p = createProduct(owner);
registerProduct(p);
return p;
}
protected abstract Product createProduct(String owner);
protected abstract void registerProduct(Product product);
}
<IDCard.java>
package ch04.A2.idcard;
import ch04.A2.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;
}
}
<IDCardFactory.java>
package ch04.A2.idcard;
import ch04.A2.framework.*;
import java.util.*;
public class IDCardFactory extends Factory {
private Hashtable database = new Hashtable();
private int serial = 100;
protected synchronized Product createProduct(String owner) {
return new IDCard(owner, serial++);
}
protected void registerProduct(Product product) {
IDCard card = (IDCard)product;
database.put(card.getOwner(), new Integer(card.getSerial()));
}
public Hashtable getDatabase() {
return database;
}
}
<Main.java>
package ch04.A2;
import ch04.A2.framework.*;
import ch04.A2.idcard.*;
public class Main {
public static void main(String[] args) {
Factory factory = new IDCardFactory();
Product card1 = factory.create("홍길동");
Product card2 = factory.create("이순신");
Product card3 = factory.create("강감찬");
card1.use();
card2.use();
card3.use();
}
}