在前面我们看到了单例模式的使用,在dubbo中,同样有单例模式的使用,找到dubbo中的ExtensionLoader类可以看到这样的代码:
/**
* Find the extension with the given name. If the specified name is not found, then {@link IllegalStateException}
* will be thrown.
*/
@SuppressWarnings("unchecked")
public T getExtension(String name) {
return getExtension(name, true);
}
获取扩展:
public T getExtension(String name, boolean wrap) {
if (StringUtils.isEmpty(name)) {
throw new IllegalArgumentException("Extension name == null");
}
if ("true".equals(name)) {
return getDefaultExtension();
}
final Holder<Object> holder = getOrCreateHolder(name);
Object instance = holder.get();
if (instance == null) {
synchronized (holder) {
instance = holder.get();
if (instance == null) {
instance = createExtension(name, wrap);
holder.set(instance);
}
}
}
return (T) instance;
}
同时在createExtension中看到装饰者模式的使用,是否需要进行装饰wrap,如果需要,则对其进行装饰:
private T createExtension(String name, boolean wrap) {
Class<?> clazz = getExtensionClasses().get(name);
if (clazz == null) {
throw findException(name);
}
try {
T instance = (T) EXTENSION_INSTANCES.get(clazz);
if (instance == null) {
EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
instance = (T) EXTENSION_INSTANCES.get(clazz);
}
injectExtension(instance);
if (wrap) {
List<Class<?>> wrapperClassesList = new ArrayList<>();
if (cachedWrapperClasses != null) {
wrapperClassesList.addAll(cachedWrapperClasses);
wrapperClassesList.sort(WrapperComparator.COMPARATOR);
Collections.reverse(wrapperClassesList);
}
if (CollectionUtils.isNotEmpty(wrapperClassesList)) {
for (Class<?> wrapperClass : wrapperClassesList) {
Wrapper wrapper = wrapperClass.getAnnotation(Wrapper.class);
if (wrapper == null
|| (ArrayUtils.contains(wrapper.matches(), name) && !ArrayUtils.contains(wrapper.mismatches(), name))) {
instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
}
}
}
}
initExtension(instance);
return instance;
} catch (Throwable t) {
throw new IllegalStateException("Extension instance (name: " + name + ", class: " +
type + ") couldn't be instantiated: " + t.getMessage(), t);
}
}
上面是使用wrapper的场景进行装饰,也可以说成是包装,本质就是装饰者模式的体现。除了wrapper,在spring中也有装饰者模式的体现。
在前面的注册beanDefintion的时候,进行默认标签解析时,会经过四步:
/**
* Process the given bean element, parsing the bean definition
* and registering it with the registry.
*/
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//解析beanDefintion元素
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
//进行装饰
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
//注册最终被装饰的实例
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
//发送注册事件
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
除了这里使用装饰者模式之外,对于wrapper的对象也是采用了装饰者模式。如果我们需要实现一个装饰者模式,那么怎样实现呢?
/**
* Decorate the given bean definition through a namespace handler, if applicable.
如果使用,通过名称空间处理程序装饰给定的beanDefintion
* @param ele the current element 当前元素ele
* @param originalDef the current bean definition 当前的beanDefintion =>originalDef
* @param containingBd the containing bean definition (if any)
* @return the decorated bean definition 返回被装饰好的beanDefintion
*/
public BeanDefinitionHolder decorateBeanDefinitionIfRequired(
Element ele, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd) {
BeanDefinitionHolder finalDefinition = originalDef;
// Decorate based on custom attributes first.
NamedNodeMap attributes = ele.getAttributes();
for (int i = 0; i < attributes.getLength(); i++) {
Node node = attributes.item(i);
finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
}
// Decorate based on custom nested elements.
NodeList children = ele.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node node = children.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
}
}
return finalDefinition;
}
进行装饰如果需要:
/**
* Decorate the given bean definition through a namespace handler,
* if applicable.
* @param node the current child node
* @param originalDef the current bean definition
* @param containingBd the containing bean definition (if any)
* @return the decorated bean definition
*/
public BeanDefinitionHolder decorateIfRequired(
Node node, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd) {
String namespaceUri = getNamespaceURI(node);
if (namespaceUri != null && !isDefaultNamespace(namespaceUri)) {
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler != null) {
BeanDefinitionHolder decorated =
handler.decorate(node, originalDef, new ParserContext(this.readerContext, this, containingBd));
if (decorated != null) {
return decorated;
}
}
else if (namespaceUri.startsWith("http://www.springframework.org/")) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", node);
}
else {
// A custom namespace, not to be handled by Spring - maybe "xml:...".
if (logger.isDebugEnabled()) {
logger.debug("No Spring NamespaceHandler found for XML schema namespace [" + namespaceUri + "]");
}
}
}
return originalDef;
}
如果debug的时候,可以看到程序中在默认标签中,如果存在自定义的标签时,此时就需要对自定义标签进行解析,此时会寻找命名空间getNamespaceURI,使用命名空间处理器进行标签的解析:this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri)。这个就是自定义标签解析的套路。
要实现装饰者模式,需要完成:
1.继承处理接口
2.提供构造函数或者set方法
3.覆盖原有接口方法
装饰者的使用场景:
如果不想要改变原有接口的实现,而又想增加新的功能或者特性时,此时就可以考虑使用装饰者模式对原有的功能进行只增强
下面我们来看一个装饰者模式的例子:
原始的例子:
在小商店还很小的时候,只提供做煎饼的业务,这个时候的样式比较单一,这个时候师傅只做煎饼,随着客户的反馈,之后在煎饼的基础之上又加上了鸡蛋,但随后有加上了香肠,形成了煎饼+鸡蛋+香肠的方式,代码来源于github…
原始接口:
public class BatterCake {
//商品信息
public String getMsg() {
return "煎饼";
}
//获取价格
public int getPrice() {
return 5;
}
}
原始的实现方式:
煎饼+鸡蛋
public class BatterCakeWithEgg extends BatterCake {
@Override
public String getMsg() {
return super.getMsg() +" + 1个鸡蛋";
}
@Override
public int getPrice() {
return super.getPrice()+1;
}
}
煎饼+鸡蛋+香肠:
//在原有煎饼+鸡蛋的基础之上,加1个香肠
public class BatterCakeWithEggAndHotdog extends BatterCakeWithEgg {
@Override
public String getMsg() {
return super.getMsg() +" + 1个香肠";
}
@Override
public int getPrice() {
return super.getPrice() +2;
}
}
进行商品、价格获取:
public class BatterCakeTest {
public static void main(String[] args) {
//创建一个对象煎饼
BatterCake batterCake = new BatterCake();
System.out.println(batterCake.getMsg() +" 的价格是:"+batterCake.getPrice());
//创建一个煎饼+鸡蛋对象
batterCake = new BatterCakeWithEgg();
System.out.println(batterCake.getMsg() +" 的价格是:"+batterCake.getPrice());
//创建一个煎饼+鸡蛋+香肠
batterCake = new BatterCakeWithEggAndHotdog();
System.out.println(batterCake.getMsg() +" 的价格是:"+batterCake.getPrice());
}
}
结果:
使用装饰者模式进行重构:
原始接口:
public abstract class BatterCake {
//商品信息
protected abstract String getMsg();
//价格
protected abstract int getPrice();
}
原始接口实现:
public class BaseBatterCake extends BatterCake {
protected String getMsg() {
return "煎饼";
}
protected int getPrice() {
return 5;
}
}
待装饰的类:
// 装饰类继承原始接口
public class BatterCakeDecorator extends BatterCake {
//原始接口对象
private BatterCake batterCake;
//提供构造函数
public BatterCakeDecorator(BatterCake batterCake) {
this.batterCake = batterCake;
}
//重写原始接口的方法
@Override
protected String getMsg() {
return this.batterCake.getMsg();
}
@Override
protected int getPrice() {
return this.batterCake.getPrice();
}
}
进行装饰:
//进行装饰:在原有的基础上进行装饰
public class BatterCakeEggDecorator extends BatterCakeDecorator {
//原始的数据构造函数
public BatterCakeEggDecorator(BatterCake batterCake) {
super(batterCake);
}
//重写原始方法
@Override
protected String getMsg() {
return super.getMsg() +" 1 个鸡蛋";
}
//重写原始方法
@Override
protected int getPrice() {
return super.getPrice() +1;
}
}
进行装饰:
//进行进一步装饰
public class BatterCakeWihHotdogDecorator extends BatterCakeDecorator {
//需要装饰的对象
public BatterCakeWihHotdogDecorator(BatterCake batterCake) {
super(batterCake);
}
//重写被装饰方法
@Override
protected String getMsg() {
return super.getMsg() +" 1 个香肠";
}
@Override
protected int getPrice() {
return super.getPrice() + 2;
}
}
进行测试:
public class BatterCakeDecoratorTest {
public static void main(String[] args) {
//原始被修饰对象
BaseBatterCake baseBatterCake = new BaseBatterCake();
//装饰对象
BatterCakeDecorator batterCakeDecorator = new BatterCakeDecorator(baseBatterCake);
//创建装饰后对象
batterCakeDecorator = new BatterCakeEggDecorator(batterCakeDecorator);
//创建最终装饰的对象
batterCakeDecorator = new BatterCakeWihHotdogDecorator(batterCakeDecorator);
System.out.println(batterCakeDecorator.getMsg() +" 的总价是: "+batterCakeDecorator.getPrice());
}
}
最终被增强的对象的信息: