重点等级::star::star::star::star::star:
动态的将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
装饰者模式中装饰者和被装饰者具有相同的超类,在这利用继承达到了“类型匹配”,而不是利用继承获得“行为”。
装饰者和被装饰者拥有同一超类。装饰者实现同一超类的接口并持有被装饰者。
- 在不影响其他对象的情况下,动态地、透明地向各个对象添加职责
- JAVA IO
java.io.InputStream, java.io.OutputStream, java.io.Reader 、java.io.Writer
java.util.Collections#synchronizedXXX()
java.util.Collections#unmodifiableXXX()
java.util.Collections#checkedXXX()
- Spring-web 对 ServletRequest 使用 ServletRequestWrapper 进行包装装饰
- Spring Security oauth2
org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter //被装饰者 org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter //装饰者
public interface Troll {
void attack();
int getAttackPower();
void fleeBattle();
}
//被装饰者
public class SimpleTroll implements Troll {
private static final Logger LOGGER = LoggerFactory.getLogger(SimpleTroll.class);
@Override
public void attack() {
LOGGER.info("The troll tries to grab you!");
}
@Override
public int getAttackPower() {
return 10;
}
@Override
public void fleeBattle() {
LOGGER.info("The troll shrieks in horror and runs away!");
}
}
//装饰者
public class ClubbedTroll implements Troll {
private static final Logger LOGGER = LoggerFactory.getLogger(ClubbedTroll.class);
private Troll decorated;
public ClubbedTroll(Troll decorated) {
this.decorated = decorated;
}
@Override
public void attack() {
decorated.attack();
LOGGER.info("The troll swings at you with a club!");
}
@Override
public int getAttackPower() {
return decorated.getAttackPower() + 10;
}
@Override
public void fleeBattle() {
decorated.fleeBattle();
}
}
// simple troll
var troll = new SimpleTroll();
troll.attack(); // The troll tries to grab you!
troll.fleeBattle(); // The troll shrieks in horror and runs away!
// 通过装饰器来更改加强 troll
var clubbedTroll = new ClubbedTroll(troll);
clubbedTroll.attack(); // The troll tries to grab you! The troll swings at you with a club!
clubbedTroll.fleeBattle(); // The troll shrieks in horror and runs away!