设计模式

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:具体工厂角色

代码示例

抽象工厂模式:

提供了一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。