Abstract Factory Pattern

HeeSeong·2021년 9월 10일
0

Design Pattern

목록 보기
3/4
post-thumbnail

Abstract Factory Pattern 이란?


상세화된 서브클래스를 정의하지 않고도 서로 관련성이 있거나 독립적인 여러 객체의 군을 생성하기 위한 인터페이스를 제공


1. 사용 의도 (Intent)


  • 추상화된 인터페이스 팩토리를 제공하고 상황에 따라 그에 맞는 인스턴스들이 생성되도록 함

  • 생성되고 구성되고 표현되는 방식과 무관하게 시스템을 독립적으로 만들고자 할 때

  • 하나 이상의 제품군들 중 하나를 선택하여 시스템을 설정해야 하고 한번 구성한 제품을 다른 것으로 대체할 수 있을 때


2. 객체 협력 (collaborations)



  • AbstractFactory
    개념적 제품에 대한 객체를 생성하는 오퍼레이션 인터페이스를 정의한다
  • ConcreteFactory
    구체적인 제품에 대한 객체를 생성하는 오퍼레이션을 구현한다.
  • AbstractProduct
    개념적 제품 객체에 대한 인터페이스를 정의한다.
  • ConcreteProduct
    구체적으로 팩토리가 생성할 객체를 정의하고, AbstractProduct 가 정의하고 있는 인터페이스를 구현한다.
  • Client
    AbstractFactory 와 AbstractProduct 클래스에 선언된 인터페이스를 사용한다.

3. 결과 (consequence)


장점


예를 들어 데이터베이스에 따라 DAO클래스가 달라져야 한다고 할 때, 현재 사용해야 하는 DB의 종류에 따른 DAO 인스턴스를 한꺼번에 생성하도록 한다.

  • 구체적인 클래스를 분리한다.
    추상 팩토리 패턴을 쓰면 응용 프로그램이 생성할 객체의 클래스를 제어할 수 있다. 팩토리는 제품 객체를 생성하는 과정과 책임을 캡슐화 한 것이기 때문에, 구체적인 구현 클래스가 사용자에게서 분리된다.

  • 제품군을 쉽게 대체할 수 있다.
    구체 팩토리를 변경함으로써 응용프로그램은 서로 다른 제품을 사용할 수 있게 변경된다. 추상 팩토리는 필요한 모든 것을 생성하기 때문에 전체 제품군은 한 번에 변경이 가능하다.


단점


  • 새로운 추가가 힘들어 확장성이 떨어진다.
    새로운 제품을 추가하려면, 관련된 추상 팩토리에 새로운 제품 생성 코드를 모두 만들어주어야 한다.

4. 예제 코드


  • UserInfo
public class UserInfo {
    private String userId;
    private String password;
    private String userName;

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserId() {
        return userId;
    }

    public String getPassword() {
        return password;
    }

    public String getUserName() {
        return userName;
    }
}

  • UserInfoDao
public interface UserInfoDao {
    void insertProduct(UserInfo userInfo);
    void updateProduct(UserInfo userInfo);
    void deleteProduct(UserInfo userInfo);
}

  • Product
public class Product {
    private String productId;
    private String productName;
    
    public void setProductId(String productId) {
        this.productId = productId;
    }

    public void setProductName(String productName) {
        this.productName = productName;
    }

    public String getProductId() {
        return productId;
    }

    public String getProductName() {
        return productName;
    }
}

  • ProductDao
public interface ProductDao {
    void insertProduct(Product product);
    void updateProduct(Product product);
    void deleteProduct(Product product);
}

  • ProductOracleDao
public class ProductOracleDao implements ProductDao {

    @Override
    public void insertProduct(Product product) {
        System.out.println("insert into Oracle DB productId = " + product.getProductId());
    }

    @Override
    public void updateProduct(Product product) {
        System.out.println("update into Oracle DB productId = " + product.getProductId());
    }

    @Override
    public void deleteProduct(Product product) {
        System.out.println("delete into Oracle DB productId = " + product.getProductId());
    }
}

  • ProductMySqlDao
public class ProductMySqlDao implements ProductDao {

    @Override
    public void insertProduct(Product product) {
        System.out.println("insert into MySql DB productId = " + product.getProductId());
    }

    @Override
    public void updateProduct(Product product) {
        System.out.println("update into MySql DB productId = " + product.getProductId());
    }

    @Override
    public void deleteProduct(Product product) {
        System.out.println("delete into MySql DB productId = " + product.getProductId());
    }
}

  • UserInfoOracleDao
public class UserInfoOracleDao implements UserInfoDao {

    @Override
    public void insertUserInfo(UserInfo userInfo) {
        System.out.println("insert into Oracle DB userId = " + userInfo.getUserId());
    }

    @Override
    public void updateUserInfo(UserInfo userInfo) {
        System.out.println("update into Oracle DB userId = " + userInfo.getUserId());
    }

    @Override
    public void deleteUserInfo(UserInfo userInfo) {
        System.out.println("delete into Oracle DB userId = " + userInfo.getUserId());
    }
}

  • UserInfoMySqlDao
public class UserInfoMySqlDao implements UserInfoDao {

    @Override
    public void insertUserInfo(UserInfo userInfo) {
        System.out.println("insert into MySql DB userId = " + userInfo.getUserId());
    }

    @Override
    public void updateUserInfo(UserInfo userInfo) {
        System.out.println("update into MySql DB userId = " + userInfo.getUserId());
    }

    @Override
    public void deleteUserInfo(UserInfo userInfo) {
        System.out.println("delete into MySql DB userId = " + userInfo.getUserId());
    }
}

  • DaoFactory
public interface DaoFactory {
    public UserInfoDao createUserInfoDao();
    public ProductDao createProductDao();
}

  • OracleDaoFactory
public class OracleDaoFactory implements DaoFactory {

    @Override
    public UserInfoDao createUserInfoDao() {
        return new UserInfoOracleDao();
    }

    @Override
    public ProductDao createProductDao() {
        return new ProductOracleDao();
    }
}

  • MySqlDaoFactory
public class MySqlDaoFactory implements DaoFactory {

    @Override
    public UserInfoDao createUserInfoDao() {
        return new UserInfoMySqlDao();
    }

    @Override
    public ProductDao createProductDao() {
        return new ProductMySqlDao();
    }
}

  • Main
import java.io.FileInputStream;
import java.util.Properties;

public class WebClient {

    public static void main(String[] args) {
        FileInputStream fis = new FileInputStream("db.properties");

        Properties prop = new Properties();
        prop.load(fis);

        String dbType = prop.getProperty("DBTYPE");

        UserInfo userInfo = new UserInfo();
        userInfo.setUserId("12345");
        userInfo.setPassword("!@#$%");
        userInfo.setUserName("이순신");

        Product product = new Product();
        product.setProductId("0011AA");
        product.setProductName("TV");

        DaoFactory daoFactory = null;

        if (dbType.equals("MYSQL"))
            daoFactory = new MySqlDaoFactory();
        else if (dbType.equals("ORACLE"))
            daoFactory = new OracleDaoFactory();
        else
            System.out.println("지원하지 않는 DB");

        UserInfoDao userInfoDao = daoFactory.createUserInfoDao();
        System.out.println("===UserInfo Transaction===");
        userInfoDao.insertUserInfo(userInfo);
        userInfoDao.updateUserInfo(userInfo);
        userInfoDao.deleteUserInfo(userInfo);
        System.out.println("===Product Transaction===");
        ProductDao productDao = daoFactory.createProductDao();
        productDao.insertProduct(product);
        productDao.updateProduct(product);
        productDao.deleteProduct(product);
    }
}

결과


db.properties에 DB 벤더명을 "MYSQL"로 하면 아래처럼 나오게 된다.

===UserInfo Transaction===
insert into MySql DB userId = 12345
update into MySql DB userId = 12345
delete into MySql DB userId = 12345

===Product Transaction===
ProductDao productDao = daoFactory.createProductDao();
insert into MySql DB productId = 0011AA
update into MySql DB productId = 0011AA
delete into MySql DB productId = 0011AA
profile
끊임없이 성장하고 싶은 개발자

0개의 댓글

관련 채용 정보