组合模式,将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。简单理解就是,整体和部分的接口定义是一致的,在使用的时候,只有调用整体的接口就行,部分接口有新增的自定义,组合到整体就可以了。
spring cloud security组合设计模式的实现
在spring cloud security中访问令牌的产生实现,就是一个典型的组合设计模式。访问令牌的接口TokenGranter定义如下:
public interface TokenGranter {
OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest);
}
ResourceOwnerPasswordTokenGranter,支持密码类型获取令牌。
ImplicitTokenGranter,支持隐式类型获取令牌。
AuthorizationCodeTokenGranter,支持授权码类型获取令牌。
ClientCredentialsTokenGranter,支持客户端类型获取令牌。
RefreshTokenGranter,支持刷新令牌。
CompositeTokenGranter,组合类。
类结构图如下:
除了CompositeTokenGranter以外,每个类都实现了TokenGranter接口,并且满足各类获取令牌的功能。CompositeTokenGranter类,组合了所有的实现,在业务调用中直接调用CompositeTokenGranter即可。CompositeTokenGranter的实现类,如下:
public class CompositeTokenGranter implements TokenGranter {
private final List<TokenGranter> tokenGranters;
public CompositeTokenGranter(List<TokenGranter> tokenGranters) {
this.tokenGranters = new ArrayList<TokenGranter>(tokenGranters);
}
public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) {
for (TokenGranter granter : tokenGranters) {
OAuth2AccessToken grant = granter.grant(grantType, tokenRequest);
if (grant!=null) {
return grant;
}
}
return null;
}
public void addTokenGranter(TokenGranter tokenGranter) {
if (tokenGranter == null) {
throw new IllegalArgumentException("Token granter is null");
}
tokenGranters.add(tokenGranter);
}
}
价格或者优惠券扩展字段的设计实现
在价格或优惠券的设计中,自定义的字段在数据库中使用ext扩展字段保存,不同业务对象自定义json数据。生成json对象的接口设计如下:
public interface PriceExtGenerator {
/**
* 生成
*/
Map<String, Object> generate(PriceSaveDto priceSaveDto);
}
LongDistancePriceExtGenerator,远途费ext生成器
GuaranteedPriceExtGenerator,保底费ext属性生成器
DailyRentPriceExtGenerator,日租费ext属性生成器
CompositePriceExtGenerator,组合类
类结构图如下:
CompositePriceExtGenerator 实现类如下:
public class CompositePriceExtGenerator implements PriceExtGenerator {
private Map<String, PriceExtGenerator> priceExtGeneratorMap;
private CompositePriceExtGenerator() {
priceExtGeneratorMap = ImmutableMap.of(
PriceCodeEnum.DAILY_RENT_PRICE.name(), new DailyRentPriceExtGenerator(),
PriceCodeEnum.GUARANTEED_PRICE.name(), new GuaranteedPriceExtGenerator(),
PriceCodeEnum.LONG_DISTANCE_PRICE.name(), new LongDistancePriceExtGenerator());
}
/**
* 生成
*/
@Override
public Map<String, Object> generate(PriceSaveDto priceSaveDto) {
String priceCode;
PriceExtGenerator priceExtGenerator;
if (Objects.isNull(priceSaveDto)
|| Objects.isNull(priceCode = priceSaveDto.getCode())
|| Objects.isNull(priceExtGenerator = PriceExtGeneratorManagerItem.INSTANCE.priceExtGeneratorMap.get(priceCode))) {
return null;
}
return priceExtGenerator.generate(priceSaveDto);
}
}