Factory 패턴
팩토리 메소드 패턴은 인스턴스를 만드는 방법을 상위클래스 측에서 결정.
하위클래스에서 구체적인 처리의 내용 하위 클래스에서 구현.
예제는 다섯개의 클래스로 구성
frame pakage;
– Product class : 추상 메소드 use 만 정의된 추상클래스
– Factory class : 메소드 create 을 구현하는 추상 클래스
idcard pakage
– IDCard class : 메소드 use를 구현
– IDCardFactory class : 메소드 createProduct, registerProduct 를 구현하고 있는 클래스
Anonymous pakage
– Main class : 동작 테스트 클래스
Product .java
package framework;
public abstract class Product {
public abstract void use();
}
Factory.java
package framework;
public abstract class Factory {
public final Product create(String owner){
Product p = createProduct(owner);registerProduct(p);
return p;
}protected abstract void registerProduct(Product product);
protected abstract Product createProduct(String owner);
}
framework 패키지의 Factory 클래스는 createProduct 추상 메소드를 만들도록 규정, registerProduct는 Product객체를 등록하는 메소드
이 때 중요한 것이 Factory 추상 메소드에서 구현 흐름!!
Product p 자료형의 createProduct(owner)메소드를 정의하고
registerProduct(p);을 실행한 뒤 p를 리턴한다.
IDCard.java
package idcard;
import framework.Product;
public class IDCard extends Product{
private String owner;
IDCard(String owner){System.out.println(owner+”카드를 만듭니다.”);
this.owner=owner;
}public void use() {
// TODO Auto-generated method stub
System.out.println(owner+”카드를 사용합니다.”);
}
public String getOwner(){
return owner;
}}
Product를 상속받아 use()메소드를 구현한다. 여기서는 IDCard 생성자를 통해 owner를 받고, 출력한뒤 멤버 변수에 넣는다.
IDCardFactory.java
package idcard;
import java.util.ArrayList;
import java.util.List;import framework.Factory;
import framework.Product;public class IDCardFactory extends Factory{
private List owners = new ArrayList();
protected void registerProduct(Product product) {
// TODO Auto-generated method stub
owners.add(((IDCard)product).getOwner());
}
protected Product createProduct(String owner) {
// TODO Auto-generated method stubreturn new IDCard(owner);
}}
여기서는 register메소드 구현을 위해 owners 라는 배열을 선언했다.(ArrayList) Factory를 상속 받았기에 createProduct와 registerProduct()메소드를 구현 하면 Factory 클래스에 구현 흐름에 따라 처리된다.
Main.java
package Anonymous;
import framework.Factory;
import framework.Product;
import idcard.IDCardFactory;public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stubFactory factory = new IDCardFactory();
Product card1 = factory.create(“홍길동”);card1.use();
}
}
출력
홍길동카드를 만듭니다.
홍길동카드를 사용합니다.
Factory 클래스의 createProduct 메소드는 추상 메소드이며, 하위클래스 에서 구현한다.
다른 방법으로는
1. 디폴트의 구현을 준비해둔다.
classFactory{
pulbic Product createProduct(String name) {
return new Product(name)
}
}
이 경우에는 Product 클래스에 직접 new를 이용하고 있어서 Product클래스를 추상클래스로 둘 수 없다.
2. 에러를 이용한다.
classFactory{
pulbic Product createProduct(String name) {
throw new RuntimeException();
}
}
디폴트의 구현 내용을 에러로 처리해두면, 하위클래스에서 구현하지 않을 경우 실행할때, 에러가 발생.
연습문제.
IDCard의 생성자가 public 이 아닌 이유는 ?
디폴트 생성자는 동일한 패키지 내에서만 사용가능
IDCard 인스턴스를 패키지 외부로 부터 new 를 사용하여 생성할 수없게끔 반드시 IDCardFactory를 경유해야 하기 때문에
public abstract class Product {
public abstract Product (String name );
public abstract void use();
}
에서 에러가 나는 이유는?
abstract한 생성자 생성 불가능 java에서 생성자는 상속되지 않기 때문에 abstract한 생성자는 의미 없음
결론.. 음 .. 좀 헷갈리지만 전체적으로 템플릿 메소드의 확장? 정도로 생각하련다. 중요한 점은 하위클래스에 위임을 하는 점과 , 전체적인 구현흐름을 추상클래스에서 정의해놓고, 구현하면 각각의 유지보수, 코드의 재이용성, 수정, 특히나 확장 면에서 유리하게 써먹을 수있다는점
'DesignPattern' 카테고리의 다른 글
Clean Architecture 번역 (0) | 2017.12.26 |
---|---|
Singlton pattern (0) | 2016.05.18 |
template pattern (0) | 2016.05.18 |
Iterator Pattern (0) | 2016.05.18 |
Adapter Pattern (0) | 2016.05.18 |