type
status
date
slug
summary
tags
category
icon
password

一、设计模式的规范

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

二、依赖倒置原则

定义:程序依赖接口,接口定义标准和规范,具体的实现按照场景,而不是使用对象硬编码的方式实现
notion image

三、示例

模拟场景: 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关系图

硬编码的方式:具体的实现都在此类里
notion image
依赖倒置方式:
notion image
总结: 依赖倒置原则增加了代码的可维护性,利用多态的特性,上级只需要定义标准,下级负责实现,跟装饰者模式有点类似
 
JAVA【设计模式】接口隔离原则JAVA【设计模式】工厂方法模式