티스토리 뷰

knowledge/pattern

[Pattern] Decorator Pattern

글을 쓰는 개발자 2022. 9. 10. 10:36
반응형

정의

객체에 추가 요소를 동적으로 더할 수 있는 패턴.

데코레이터를 사용하면 서브클래스를 만들 때보다 훨신 유연하게 기능을 확장할 수 있다.

관련 내용

  • 데코레이터의 슈퍼클래스는 자신이 장식하고 있는 객체의 슈퍼클래스와 같다.
  • 한 객체를 여러 개의 데코레이터로 감쌀 수 있다.
  • 데코레이터는 자신이 감싸고 있는 객체와 같은 슈퍼클래스를 가지고 있기에 원래 객체가 들어갈 자리에 데코레이터 객체를 넣어도 상관없다.
  • 데코레이터는 자신이 장식하고 있는 객체에게 어떤 행동을 위임하는 일 말고도 추가 작업을 수행할 수 있다.
  • 객체는 어제든지 감쌀 수 있으므로 실행 중에 필요한 데코레이터를 마음대로 적용할 수 있다.

Spring에서 보는 Decorator Pattern

여기서 슈퍼클래스는 ApplicationContext를 의미하며 데코레이터 패턴으로 돌아가는 메소드는 setParent로 동작하는 모습을 볼 수 있습니다.

코드를 보면 이전에 정의한 부모의 정보와 현재 객체의 정보를 merge하는 모습을 봤을 때 데코레이터 패턴임을 암시할 수 있습니다.

 

ApplicationContext

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,  
      MessageSource, ApplicationEventPublisher, ResourcePatternResolver {   
    @Nullable  
    ApplicationContext getParent();

ConfigurableApplicationContext

/**  
 * Set the parent of this application context. * <p>Note that the parent shouldn't be changed: It should only be set outside  
 * a constructor if it isn't available when an object of this class is created, * for example in case of WebApplicationContext setup. * @param parent the parent context  
 * @see org.springframework.web.context.ConfigurableWebApplicationContext  
 */
void setParent(@Nullable ApplicationContext parent);

AbstractApplicationContext

/** Parent context. */  
@Nullable  
private ApplicationContext parent;

@Override  
public void setParent(@Nullable ApplicationContext parent) {  
   this.parent = parent;  
   if (parent != null) {  
      Environment parentEnvironment = parent.getEnvironment();  
      if (parentEnvironment instanceof ConfigurableEnvironment) {  
         getEnvironment().merge((ConfigurableEnvironment) parentEnvironment);  
      }  
   }  
}

GenericApplicationContext

public GenericApplicationContext(@Nullable ApplicationContext parent) {  
   this();  
   setParent(parent);  
}
@Override  
public void setParent(@Nullable ApplicationContext parent) {  
   super.setParent(parent);  
   this.beanFactory.setParentBeanFactory(getInternalParentBeanFactory());  
}

Test

@Test  
public void testAspectsAndAdvisorAreAppliedEvenIfComingFromParentFactory() {  
   ClassPathXmlApplicationContext ac = newContext("aspectsPlusAdvisor.xml");  

   GenericApplicationContext childAc = new GenericApplicationContext(ac);  
   // Create a child factory with a bean that should be woven  
   RootBeanDefinition bd = new RootBeanDefinition(TestBean.class);  
   bd.getPropertyValues().addPropertyValue(new PropertyValue("name", "Adrian"))  
         .addPropertyValue(new PropertyValue("age", 34));  
   childAc.registerBeanDefinition("adrian2", bd);  
   // Register the advisor auto proxy creator with subclass  
   childAc.registerBeanDefinition(AnnotationAwareAspectJAutoProxyCreator.class.getName(), new RootBeanDefinition(  
         AnnotationAwareAspectJAutoProxyCreator.class));  
   childAc.refresh();  

   ITestBean beanFromChildContextThatShouldBeWeaved = (ITestBean) childAc.getBean("adrian2");  
   //testAspectsAndAdvisorAreApplied(childAc, (ITestBean) ac.getBean("adrian"));  
   doTestAspectsAndAdvisorAreApplied(childAc, beanFromChildContextThatShouldBeWeaved);  
}
반응형

'knowledge > pattern' 카테고리의 다른 글

[Pattern] Factory Pattern  (0) 2022.09.10
[Pattern] Observer Pattern  (0) 2022.08.27
[Pattern] Strategy Pattern  (0) 2022.08.10
[Pattern] Facade Pattern  (0) 2021.12.12
[Pattern] Composite Pattern에 대하여  (0) 2021.11.29
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함