템플릿 메서드를 사용하는 생성 메서드 패턴
모든 디자인 패턴의 목표는 구조와 구현의 분리에 있다.
- 객체 생성이 클래스 자신을 뜻하지 않아도 된다.
- 메서드 오버로딩 시 리턴타입은 영향을 주지 않는데, 팩토리메서드는 리턴 값이 다른 생성 메서드를 가질 수 있다.
- 내부에서 생성 과정이 여러가지 일 경우 Template Method 와 함께 사용될 수 있다.
- 객체를 만드는 추상클래스(Template Method, Factory Method) + 만들 객체의 인터페이스로 골격을 갖춘다.
- 추상클래스의 상속 클래스에서 만들 객체의 인터페이스의 구현체를 만들어내는 틀을 가진다.
Product 인터페이스 / 구현 클래스
public interface Product {
void use();
}
class CorporationCard implements Product {
private String owner;
CorporationCard(String owner) {
this.owner = owner;
}
@Override
public void use() {
System.out.printf("%s 의 카드를 사용합니다.",owner);
}
}
class IDCard implements Product {
private String owner;
IDCard(String owner) {
this.owner = owner;
}
@Override
public void use() {
System.out.printf("%s 의 카드를 사용합니다.%n",owner);
}
}
Factory 추상클래스 ( 템플릿 메서드 패턴을 따르고 있다.) / Product 구현체에 맞는 Factory
public abstract class Factory {
//템플릿 메서드
protected abstract Product createProduct(String owner);
protected abstract void loggingProduct(Product product);
//팩토리 메소드
public final Product created(String owner){
Product product = createProduct(owner);
loggingProduct(product);
return product;
}
}
public class CorporationCardFactory extends Factory {
@Override
protected Product createProduct(String owner) {
return new CorporationCard(owner);
}
@Override
protected void loggingProduct(Product product) {
System.out.printf("사용 중인 Product 클래스 : %s %n" , product.getClass());
}
}
public class IDCardFactory extends Factory {
@Override
protected Product createProduct(String owner) {
return new IDCard(owner);
}
@Override
protected void loggingProduct(Product product) {
System.out.printf("사용 중인 Product 클래스 : %s %n" , product.getClass());
}
}
메인 메서드 호출
public class Main {
public static void main(String[] args) {
Factory idCardFactory = new IDCardFactory();
Product soominCard = idCardFactory.created("Soomin");
soominCard.use();
Factory corporationCardFactory = new CorporationCardFactory();
Product copCard = corporationCardFactory.created("cop");
copCard.use();
}
}
// 로그
사용 중인 Product 클래스 : class Factory.IDCard
Soomin 의 카드를 사용합니다.
사용 중인 Product 클래스 : class Factory.CorporationCard
cop 의 카드를 사용합니다.
즉 객체를 만들어내는 부분을 Sub-Class에 위임하는 것이다.
하나의 팩토리 메서드를 가지고 다양한 구현체를 찍어내는 방법
DriverManager.getConnection() 메서드가 이런 형태를 띈다고 생각해 왔다. 하나의 팩토리 메서드 라고 보았다.
Robot 과 리턴시킬 구현체들
public interface Robot {
void printName();
}
public class DefaultRobot implements Robot {
private final static String MODEL = "Default Version";
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void printName() {
System.out.printf("해당 로봇 모델은 %s 입니다. 기종 이름은 %s 입니다. %n",MODEL,name);
}
}
public class ModifiedRobot implements Robot {
private final static String MODEL = "Modified Version";
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void printName() {
System.out.printf("해당 로봇 모델은 %s 입니다. 기종 이름은 %s 입니다. %n",MODEL,name);
}
}
ClassName , Keyword 로 원하는 객체를 만들어내는 Factory
public abstract class RobotFactory {
public abstract Robot createModel(String str,String name);
}
public class ClassNameRobotFactory extends RobotFactory {
@Override
public Robot createModel(String className,String name) {
try{
Class<?> clazz = Class.forName(className);
Robot obj = (Robot)clazz.newInstance();
if(obj instanceof DefaultRobot){
DefaultRobot defaultRobot = (DefaultRobot)obj;
defaultRobot.setName(name);
return defaultRobot;
}
ModifiedRobot modifiedRobot = (ModifiedRobot)obj;
modifiedRobot.setName(name);
return modifiedRobot;
}catch(Exception e){
e.printStackTrace();
return null;
}
}
}
public class KeywordRobotFactory extends RobotFactory {
@Override
public Robot createModel(String keyword,String name) {
switch (keyword){
case "default":
DefaultRobot defaultRobot = new DefaultRobot();
defaultRobot.setName(name);
return defaultRobot;
case "modified":
ModifiedRobot modifiedRobot = new ModifiedRobot();
modifiedRobot.setName(name);
return modifiedRobot;
default:
return null;
}
}
}
호출하는 메인메서드와 로깅
public class Main {
public static void main(String[] args) {
RobotFactory classNameRobotFactory = new ClassNameRobotFactory();
Robot deedea = classNameRobotFactory.createModel("Factory.HeadFirst.DefaultRobot","deedea");
Robot tom = classNameRobotFactory.createModel("Factory.HeadFirst.ModifiedRobot", "tom");
deedea.printName();
tom.printName();
System.out.println("===========================================================");
RobotFactory keywordRobotFactory = new KeywordRobotFactory();
Robot defaultModel = keywordRobotFactory.createModel("default", "deedea");
Robot modifiedModel = keywordRobotFactory.createModel("modified", "tom");
defaultModel.printName();
modifiedModel.printName();
}
}
////로깅
해당 로봇 모델은 Default Version 입니다. 기종 이름은 deedea 입니다.
해당 로봇 모델은 Modified Version 입니다. 기종 이름은 tom 입니다.
===========================================================
해당 로봇 모델은 Default Version 입니다. 기종 이름은 deedea 입니다.
해당 로봇 모델은 Modified Version 입니다. 기종 이름은 tom 입니다.
'Design Pattern' 카테고리의 다른 글
Prototype (0) | 2020.11.29 |
---|---|
SingleTon Pattern (0) | 2020.11.24 |
Template Method (0) | 2020.11.23 |
Adapter (0) | 2020.11.23 |
Strategy (0) | 2020.11.23 |