文章目录
- 依赖倒置原则
- 依赖倒置原则实战
- 使用依赖倒置原则进行改变
- 案例中两种方式的类图
依赖倒置原则
定义:
程序要依赖于抽象接口, 不要依赖于具体实现, 对抽象进行编程, 而不是对实现进行编程, 降低了客户与实现模块的耦合.
高层模块不应该依赖底层模块, 都应该依赖抽象(接口 抽象类)
上级找下级, 一般不会直接找你 ,而是通过助理等找到.
下级去依赖上级的标准等. 上级出的标准, 不需要去关心下级如何去实现的. 降低上级的耦合性.
spring的spi机制等.
依赖倒置原则实战
随机抽奖与权重抽奖.
不使用依赖倒置原则的写法 :
定义抽奖用户类
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 {/**// 随机抽奖* @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<BetUser>();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 (e == 0) {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 ApiTest {private Logger logger = LoggerFactory.getLogger(ApiTest.class);@Testpublic void test_DrawControl() {List<BetUser> betUserList = new ArrayList<>();betUserList.add(new BetUser("花花", 65));betUserList.add(new BetUser("豆豆", 43));betUserList.add(new BetUser("小白", 72));betUserList.add(new BetUser("笨笨", 89));betUserList.add(new BetUser("丑蛋", 10));DrawControl drawControl = new DrawControl();List<BetUser> prizeRandomUserList = drawControl.doDrawRandom(betUserList, 3);logger.info("随机抽奖, 中奖用户:{}", JSON.toJSON(prizeRandomUserList));List<BetUser> prizeWeightUserList = drawControl.doDrawWeight(betUserList, 3);logger.info("权重抽奖, 中奖用户名单:{}", JSON.toJSON(prizeWeightUserList));}
}
控制台打印如下 :
随机抽奖, 中奖用户:[{“userWeight”:10,“userName”:“丑蛋”},{“userWeight”:65,“userName”:“花花”},{“userWeight”:43,“userName”:“豆豆”}]
权重抽奖, 中奖用户名单:[{“userWeight”:89,“userName”:“笨笨”},{“userWeight”:72,“userName”:“小白”},{“userWeight”:65,“userName”:“花花”}]
使用依赖倒置原则进行改变
抽奖用户类与上面一致, 定义一个抽奖的接口
public interface IDraw {/*** 获取抽奖用户方法* @param list 参与 抽奖的人* @param count 中奖人数* @return*/List<BetUser> prize(List<BetUser> list, int count);
}
分别创建随机抽奖类和权重抽奖类, 实现抽奖接口
public class DrawRandom implements IDraw{@Overridepublic List<BetUser> prize(List<BetUser> list, int count) {if (list.size() <= count) {return list;}// 集合乱序Collections.shuffle(list);// 取出指定数量的中奖用户List<BetUser> prizeList = new ArrayList<BetUser>();for (int i = 0; i < count; i++) {prizeList.add(list.get(i));}return prizeList;}
}public class DrawWeightRank implements IDraw {@Overridepublic List<BetUser> prize(List<BetUser> list, int count) {//按权重排序list.sort((o1, o2) -> {int e = o2.getUserWeight() - o1.getUserWeight();if (e == 0) {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);}
}
测试类. drawControl.doDraw
方法中分别new 随机抽奖和权重抽奖.
public class ApiTest {private Logger logger = LoggerFactory.getLogger(ApiTest.class);@Testpublic void test_DrawControl() {List<BetUser> betUserList = new ArrayList<>();betUserList.add(new BetUser("花花", 65));betUserList.add(new BetUser("豆豆", 43));betUserList.add(new BetUser("小白", 72));betUserList.add(new BetUser("笨笨", 89));betUserList.add(new BetUser("丑蛋", 10));DrawControl drawControl = new DrawControl();List<BetUser> prizeRandomUserList = drawControl.doDraw(new DrawRandom(), betUserList, 3);logger.info("随机抽奖, 中奖用户名单:{}", JSON.toJSON(prizeRandomUserList));List<BetUser> prizeWeightUserList = drawControl.doDraw(new DrawWeightRank(), betUserList, 3);logger.info("权重抽奖, 中奖用户名单:{}", JSON.toJSON(prizeWeightUserList));}
}
控制台打印如下
随机抽奖, 中奖用户名单:[{“userWeight”:72,“userName”:“小白”},{“userWeight”:10,“userName”:“丑蛋”},{“userWeight”:43,“userName”:“豆豆”}]
权重抽奖, 中奖用户名单:[{“userWeight”:89,“userName”:“笨笨”},{“userWeight”:72,“userName”:“小白”},{“userWeight”:65,“userName”:“花花”}]
案例中两种方式的类图
未使用依赖倒置时, 抽奖控制类直接实现两种不同的抽奖方法
使用依赖倒置, 抽奖控制类只需传递抽奖控制的接口, 无需知道底层实现.