设计模式
1.策略模式
定义:
策略模式定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
UML结构图:
角色:
- 环境(Context)角色:持有一个Strategy引用
- 抽象策略(Strategy)角色:接口或抽象类
- 具体策略(ConcreteStrategy)角色:包含具体的算法或行为
代码示例:
public class Context {
private Strategy strategy;
private void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
private void performMethod() {
strategy.method();;
}
public static void main(String[] args) {
Strategy strategy = new ConcreteStrategyA();
Context context = new Context();
context.setStrategy(strategy);
context.performMethod();
}
}
public interface Strategy {
void method();
}
public class ConcreteStrategyA implements Strategy {
public void method() {
System.out.println("ConcreteStrategyA method!");
}
}
public class ConcreteStrategyB implements Strategy {
public void method() {
System.out.println("ConcreteStrategyB method!");
}
}
2.观察者模式
定义
观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
结构
角色
- 抽象主题:提供一个接口,可以增加和删除观察者对象
- 具体主题:将有关状态存入具体观察者对象;在具体主题内部状态发生改变时,给所有登记过的观察者发出通知
- 抽象观察者:为所有具体观察者定义一个接口,在得到主题通知时更新自己
- 具体观察者 ###代码示例
这里我们结合项目中用的eventBus来做示例,eventBus是一款发布/订阅事件总线,线程之间传递消息,优点是开销小,代码更优雅,以及将发送者和接收者解耦。
新建一个eventBus工厂:
public class EventBusFactory {
private static EventBusFactory instance = new EventBusFactory();
private AsyncEventBus eventBus = null;
public static EventBusFactory $() {
return instance;
}
private EventBusFactory() {
eventBus = new AsyncEventBus(Executors.newCachedThreadPool());
}
public void registerSubscriber(Object subscriber) {
eventBus.register(subscriber);
}
public void unRegisterSubscriber(Object subscriber) {
eventBus.unregister(subscriber);
}
public void postEvent(Object e) {
eventBus.post(e);
}
}
再新建两个event事件:
@Data
public class UpdateCacheByLabelEvent {
private List<Integer> labelIdList;
public UpdateCacheByLabelEvent(List<Integer> labelIdList) {
this.labelIdList = labelIdList;
}
}
public class UpdateCacheBySkuEvent {
private int groupId;
private List<Integer> skuIdList;
public UpdateCacheBySkuEvent(int groupId, List<Integer> skuIdList) {
this.groupId = groupId;
this.skuIdList = skuIdList;
}
}
这两个时间分别代表更新label纬度的缓存和更新sku纬度的缓存。
再定义两个订阅者, 分别处理上面的两个event事件:
public class CacheByLabelSubscriber {
@Autowired
private LabelSkuCacheService labelSkuCacheService;
@Autowired
private LabelSkuService labelSkuService;
//调用更新标签纬度缓存接口
@Subscribe
public void handleUpdateCacheByLabel(UpdateCacheByLabelEvent updateCacheByLabelEvent) {
log.info("Receive updateCacheByLabelEvent:{}", updateCacheByLabelEvent);
if (null == updateCacheByLabelEvent && CollectionUtils.isEmpty(updateCacheByLabelEvent.getLabelIdList())) {
return;
}
for (Integer labelId : updateCacheByLabelEvent.getLabelIdList()) {
List<LabelSkuDto> labelSkuDtoList = labelSkuService.getSkuInfoListByLabel(labelId);
if (CollectionUtils.isEmpty(labelSkuDtoList)) {
//删除
labelSkuCacheService.deleteLabelSkuListByLabelId(labelId);
} else {
//更新
labelSkuCacheService.setLabelSkuListByLabelId(labelId, labelSkuDtoList);
}
}
log.info("handle updateCacheByLabelEvent:{} end", updateCacheByLabelEvent);
}
}
public class CacheBySkuSubscriber {
@Autowired
private LabelSkuCacheService labelSkuCacheService;
@Autowired
private LabelSkuService labelSkuService;
//调用更新商品纬度缓存接口
@Subscribe
public void handleUpdateCacheBySku(UpdateCacheBySkuEvent updateCacheBySkuEvent) {
log.info("Receive updateCacheBySkuEvent:{}", updateCacheBySkuEvent);
if (null == updateCacheBySkuEvent && CollectionUtils.isEmpty(updateCacheBySkuEvent.getSkuIdList()) && updateCacheBySkuEvent.getGroupId() <= 0) {
return;
}
int groupId = updateCacheBySkuEvent.getGroupId();
for (Integer skuId : updateCacheBySkuEvent.getSkuIdList()) {
List<LabelDto> labelDtoList = labelSkuService.getLabelListBySkuId(skuId, groupId);
if (CollectionUtils.isEmpty(labelDtoList)) {
//删除
labelSkuCacheService.deleteLabelListBySkuId(groupId, skuId);
} else {
//更新
labelSkuCacheService.setLabelListBySkuId(groupId, skuId, labelDtoList);
}
}
log.info("handle updateCacheBySkuEvent:{} end", updateCacheBySkuEvent);
}
最后再将两个订阅者注册到eventBus上:
@Component
public class SubscribeCenter {
@Autowired
private CacheByLabelSubscriber cacheByLabelSubscriber;
@Autowired
private CacheBySkuSubscriber cacheBySkuSubscriber;
@PostConstruct
public void onStart() {
EventBusFactory.$().registerSubscriber(cacheByLabelSubscriber);
EventBusFactory.$().registerSubscriber(cacheBySkuSubscriber);
}
}
3.装饰者模式
定义
装饰者模式动态地将责任附近在对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
结构
角色
Component:一般是一个抽象类 ConcreteComponent:继承自Component,这个类就是被装饰的对象 Decorator:继承自抽象类,装饰者需要共同实现的接口,用来保证装饰者和被装饰者有共同的超类,并保证每一个装饰者都有一些必须具有的性质,如每一个装饰者都有一个实例变量来保存某个Component类型的引用 ConcreteDecorator:用来装饰Component类型的类
代码示例
4.工厂模式
定义
工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个,工厂方法让类把实例化推迟到子类
结构
角色
product:抽象产品角色 ConcreProduct:具体产品角色 Creator:抽象工厂角色 ConcreCreator:具体工厂角色
代码示例
抽象工厂模式:
提供了一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。