&emsp?依赖倒置指的是高层模块不应该依赖于底层模块,二者都应该依赖于抽象。抽象不应该依赖于细节,细节应该依赖于抽象。
未优化案例
??案例中以抽奖场景为背景,设计了两种不同的抽奖方式(抽奖逻辑对不对先不管,主要是为了演示)。
public class BetUser {
private String userName;
private int userWeight;
public BetUser() {
}
public BetUser(String userName, int userWeight) {
this.userName = userName;
this.userWeight = userWeight;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public int getUserWeight() {
return userWeight;
}
public void setUserWeight(int userWeight) {
this.userWeight = userWeight;
}
}
public class DrawControl {
public List<BetUser> doDrawRandom(List<BetUser> list, int count) {
if (list.size() <= count) return list;
Collections.shuffle(list);
List<BetUser> prizeList = new ArrayList<>(count);
for (int i = 0; i < count; i++) {
prizeList.add(list.get(i));
}
return prizeList;
}
public List<BetUser> doDrawWeight(List<BetUser> list, int count) {
list.sort((o1, o2) -> {
int e = o2.getUserWeight() - o1.getUserWeight();
if (0 == e) return 0;
return e > 0 ? 1 : -1;
});
List<BetUser> prizeList = new ArrayList<>(count);
for (int i = 0; i < count; i++) {
prizeList.add(list.get(i));
}
return prizeList;
}
}
??这样实现的问题同样在于后续维护和扩展。在扩展时,每次都要直接在类中新增代码逻辑,这样容易导致代码行数过多,代码量迅速膨胀,可读性大大降低,也不利于维护,而且对于调用方来说需要了解不同方法的逻辑调用合适的方法,增加风险和开发难度。
用依赖倒置原则优化代码
public interface IDraw {
List<BetUser> prize(List<BetUser> list, int count);
}
public class DrawRandom implements IDraw {
@Override
public List<BetUser> prize(List<BetUser> list, int count) {
if (list.size() <= count) return list;
Collections.shuffle(list);
List<BetUser> prizeList = new ArrayList<>(count);
for (int i = 0; i < count; i++) {
prizeList.add(list.get(i));
}
return prizeList;
}
}
public class DrawWeightRank implements IDraw {
@Override
public List<BetUser> prize(List<BetUser> list, int count) {
list.sort((o1, o2) -> {
int e = o2.getUserWeight() - o1.getUserWeight();
if (0 == e) return 0;
return e > 0 ? 1 : -1;
});
List<BetUser> prizeList = new ArrayList<>(count);
for (int i = 0; i < count; i++) {
prizeList.add(list.get(i));
}
return prizeList;
}
}
public class DrawControl {
public List<BetUser> doDraw(IDraw draw, List<BetUser> betUserList, int count) {
return draw.prize(betUserList, count);
}
}
??在优化的代码中,将抽奖的功能先抽象出一个接口,然后根据不同的需要用不同的类继承接口实现逻辑,这样在实际调用时只需调用传入的接口的方法,具体实现由实现类完成,调用方不用关心实现细节,同时,不同的实现拆分为不同的实现类,可读性变得更好,也有利于维护。
参考资料:《重学Java设计模式》
|