
其他 - 设计模式
2022年5月12日大约 3 分钟
1. 工厂 + 策略模式
场景
适合需要写很多 if/else 判断、具有相同属性/方法的多种实例调用,比如聚合支付、打折策略
模式概要
- 工厂模式:工厂模式是一种创建型设计模式,它提供了一种创建对象的方式,而无需在代码中明确指定要创建的具体类。工厂模式通过定义一个接口或抽象类,让子类决定要实例化的类是哪一个,从而把对象的创建过程抽象化。
- 策略模式:策略模式是一种行为型设计模式,它定义了一系列算法,把它们一个个封装起来,并且使它们可以相互替换。本模式使得算法可以独立于使用它的客户端变化。通常包含公共接口类、策略实现类以及 Context
DEMO
比如我要实现调用任一 DOTA2 英雄某个技能的功能,如果暴力 if/else 很难维护。可以使用工厂+策略模式,工厂模式负责产生不同影响技能的实例(相当于实现策略模式的 Context),策略模式负责实现不同英雄的策略逻辑。
先定义一个通用的技能策略接口
public interface HeroesSkillStrategy {
public void Q();
public void W();
public void E();
public void R();
}
接着写不同英雄的技能逻辑
public class TinkerSkillImpl implements HeroesSkillStrategy{
@Override
public void Q() {
System.out.println("Tinker --- 1技能");
}
@Override
public void W() {
System.out.println("Tinker --- 2技能");
}
@Override
public void E() {
System.out.println("Tinker --- 3技能");
}
@Override
public void R() {
System.out.println("Tinker --- 4技能");
}
}
public class ViperSkillImpl implements HeroesSkillStrategy{
@Override
public void Q() {
...
}
@Override
public void W() {
...
}
@Override
public void E() {
...
}
@Override
public void R() {
...
}
}
生成不同英雄的实例,使用枚举可以更好地维护英雄集合,方便后面工厂类的构造。
public enum HeroesEnum {
VIPER(1, ViperSkillImpl.class),
LICH(2, LichSkillImpl.class),
TINKER(3, TinkerSkillImpl.class);
HeroesEnum(int type, Class className){
this.type = type;
this.className = className;
}
public HeroesSkillStrategy getStrategyByType(int type) {
for(HeroesEnum item: HeroesEnum.values()){
if (type == item.getType()){
try {
return (HeroesSkillStrategy) item.getClassName().newInstance();
}catch (InstantiationException | IllegalAccessException e){
System.out.println("error");
}
}
}
return null;
}
public int getType() {
return type;
}
private final int type;
public Class getClassName() {
return className;
}
private final Class<HeroesSkillStrategy> className;
}
public class PayStrategyFactory {
private static Map<Integer, HeroesSkillStrategy> strategies = new HashMap<>();
public static HeroesSkillStrategy getStrategyByType(int type){
return strategies.get(type);
}
static {
for (HeroesEnum hero: HeroesEnum.values()){
strategies.put(hero.getType(), hero.getStrategyByType(hero.getType()));
}
}
}
最后,只需要根据枚举类中的 type 类型就实现了指定英雄技能的调用。如果后续需要新增英雄,只需要新增一个枚举值,并新增相应的策略实现类即可,
public class Client {
public static void main(String[] args) {
PayStrategyFactory.getStrategyByType(HeroesEnum.VIPER.getType()).Q();
}
}
2. 建造者
定义
建造者模式是一种创建型设计模式,它允许用户通过一步一步地构建复杂对象。它通过将对象的构造过程与表示分离,使得相同的构建过程可以创建不同的表示。
使用场景
目前用到比较多的是流式构造一个对象
//不用建造者
xxxDO xd = new xxxDO();
xd.setAA("aa");
xd.setBB("bb");
...
//使用建造者模式
xxxDO xd = new Builder().setAA("aa")
.setBB("bbb")
.setCC("cccc")