定义
高层模块不应该依赖底层模块,二者都应该依赖抽象。抽象不依赖具体细节,细节依赖抽象。
程序依赖于抽象接口,不依赖于具体显示。简单来说面向抽象进行编程,不要对实现编程。
模拟场景
模拟抽奖,有随机抽奖和按权重抽奖的方式。
抽奖用户定义
/**
* @description:抽奖用户
* @version: 1.0
* @Author blackcat
*/
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;
}
}
违背原则方法
/**
* @description:抽奖服务
* @Author blackcat
*/
public class DrawControl {
/**
* 随机抽取指定数量的用户,作为中奖用户
* @param list
* @param count
* @return
*/
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;
}
/**
* 权重排名获取指定数量的用户,作为中奖用户
* @param list
* @param count
* @return
*/
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;
}
}
依赖倒置原则改善代码
接口定义
/**
* @description:抽奖接口
* @version: 1.0
* @Author blackcat
*/
public interface IDraw {
List<BetUser> prize(List<BetUser> list, int count);
}
随意抽奖
/**
* @description:随机抽奖
* @version: 1.0
* @Author blackcat
*/
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;
}
}
权重抽奖
/**
* @description:按权重抽奖
* @version: 1.0
* @Author blackcat
*/
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;
}
}
抽奖服务
/**
* @description:抽奖服务
* @version: 1.0
* @Author blackcat
*/
public class DrawControl {
//IDraw 可根据抽奖类型工厂模式获取
public List<BetUser> doDraw(IDraw draw, List<BetUser> betUserList, int count) {
return draw.prize(betUserList, count);
}
}
总结
依赖倒置原则也是为了松耦合