设计模式--设计原则--依赖倒置原则

29 阅读2分钟

定义

高层模块不应该依赖底层模块,二者都应该依赖抽象。抽象不依赖具体细节,细节依赖抽象。

程序依赖于抽象接口,不依赖于具体显示。简单来说面向抽象进行编程,不要对实现编程。

模拟场景

模拟抽奖,有随机抽奖和按权重抽奖的方式。

抽奖用户定义

/**
 * @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);
    }
}

总结

依赖倒置原则也是为了松耦合

image.png