JAVA【设计模式】依赖倒置原则

一、设计模式的规范

设计模式遵循六⼤原则;单⼀职责( ⼀个类和⽅法只做⼀件事 )、⾥⽒替换( 多态,⼦类可扩展⽗类 )、依赖
倒置( 细节依赖抽象,下层依赖上层 )
、接⼝隔离( 建⽴单⼀接⼝ )、迪⽶特原则( 最少知道,降低耦合 )、开闭
原则( 抽象架构,扩展实现 ),会在具体的设计模式章节中,进⾏体现。

二、依赖倒置原则

定义:程序依赖接口,接口定义标准和规范,具体的实现按照场景,而不是使用对象硬编码的方式实现
在这里插入图片描述

三、示例

模拟场景:
1、例如:领导有事需要开部门例会,领导是不可能去每个工位,喊各位同事去参加会议。领导只会在工作群里面申明,今天什么时间段开会,各位收到消息后,自行去开会。。。

2:例如:用户抽奖有随机抽奖和权重抽奖两种方式,我们只需要定义出一套抽奖抽象标准。具体的实现,看随机和权重的不同实现。

非依赖倒置原则(硬编码)

投注用户:BetUser

package com.qf.principle.dependenceinverse.tradition;

/**
 * @description 投注用户
 */
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;
    }
}

抽奖控制,硬编码里面的实现方式:DrawControl

package com.qf.principle.dependenceinverse.tradition;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @description 抽奖控制
 */
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;
    }

}

测试:ApiTest

package com.qf.principle.dependenceinverse.tradition;

import com.alibaba.fastjson.JSON;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

public class ApiTest {

    private Logger logger = LoggerFactory.getLogger(ApiTest.class);

    @Test
    public 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));
    }

}

依赖倒置原则

投注用户:BetUser

package com.qf.principle.dependenceinverse.design;

/**
 * @description 投注用户
 */
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;
    }
}

定义接口抽奖:IDraw

package com.qf.principle.dependenceinverse.design;


import java.util.List;

public interface IDraw {
    List<BetUser> prize(List<BetUser> list, int count);
}

随机抽奖实现:RandomDraw

package com.qf.principle.dependenceinverse.design;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class RandomDraw 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;
    }
}

权重抽奖实现:WeightDraw

package com.qf.principle.dependenceinverse.design;

import java.util.ArrayList;
import java.util.List;

public class WeightDraw 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;
    }
}

抽奖控制:DrawControl

package com.qf.principle.dependenceinverse.design;


import java.util.List;

/**
 * @description 抽奖控制
 */
public class DrawControl {

    private IDraw draw;

    public List<BetUser> doDraw(IDraw draw,List<BetUser> list, int count){
      return   draw.prize(list,count);
    }
}

测试:ApiTest

package com.qf.principle.dependenceinverse.design;

import com.alibaba.fastjson.JSON;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

public class ApiTest {
    private Logger logger = LoggerFactory.getLogger(com.qf.principle.dependenceinverse.tradition.ApiTest.class);

    @Test
    public 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 RandomDraw(),betUserList,3);
        logger.info("随机抽奖,中奖用户名单:{}", JSON.toJSON(prizeRandomUserList));

        List<BetUser> prizeWeightUserList=drawControl.doDraw(new WeightDraw(),betUserList,3);
        logger.info("权重抽奖,中奖用户名单:{}", JSON.toJSON(prizeWeightUserList));
    }
}

UML关系图

硬编码的方式:具体的实现都在此类里
在这里插入图片描述
依赖倒置方式:
在这里插入图片描述
总结:
依赖倒置原则增加了代码的可维护性,利用多态的特性,上级只需要定义标准,下级负责实现,跟装饰者模式有点类似

posted @ 2022-08-30 22:40  雾托邦  阅读(76)  评论(0编辑  收藏  举报