>>分享Java编程技术,对《Java面向对象编程》等书籍提供技术支持 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 14551 个阅读者 刷新本主题
 * 贴子主题:  Java设计模式:接口隔离原则和迪米特法则详解 回复文章 点赞(0)  收藏  
作者:javathinker    发表时间:2021-06-20 08:12:15     消息  查看  搜索  好友  复制  引用

                

一、接口隔离原则

使用多个接口,而不使用单一的接口,客户端不应该依赖它不需要的接口。尽量的细化接口的职责,降低类的耦合度

我们先来看一个例子:

小明家附近新开了一家动物园,里面有老虎、鸟儿、长颈鹿.....周末在逛动物园的时候,小明突发奇想,想用一种方式记录一下这些动物的习性,于是他将老虎和鸟儿的习性结合了一下,写了下面这段代码:

动物行为

// 动物行为
public interface Animal {

    // 吃
    public void eat();

    // 游泳
    public void swim();

    // 飞
    public void fly();
}

老虎Tiger

// 老虎
public class Tiger implements Animal {
    @Override
    public void eat() {
        System.out.println("老虎在吃鸡肉.....");
    }

    @Override
    public void swim() {
        System.out.println("老虎在游泳.....");
    }

    @Override
    public void fly() {
        System.out.println("老虎不能飞.....");
    }
}

小鸟Brid

// 小鸟
public class Brid implements Animal {
    @Override
    public void eat() {
        System.out.println("小鸟在吃虫子.....");
    }

    @Override
    public void swim() {
        System.out.println("小鸟不会游泳.....");
    }

    @Override
    public void fly() {
        System.out.println("小鸟正在飞.....");
    }
}

写完上面的三段代码后,小明发现了问题:在Animal接口的三个方法中,Tiger是不会飞的,所以fly()方法对于Tiger是没有用的;Bird是不会游泳的,所以swim()方法对于Bird是没有用的。这样一来,Brid类和Tiger类都会空置一个方法,对于代码的结构设计来说不太合理。于是,他划掉了上面的三段代码,仔细思索了一会儿,写出了下面这几段代码:

// 游泳
public interface ISwim {
    public void swim();
}

// 吃
public interface IEat {
    public void eat();
}

// 飞
public interface IFly {
    public void fly();
}

小鸟Bird

// 小鸟
public class Brid implements IEat,IFly {
    @Override
    public void eat() {
        System.out.println("小鸟在吃虫子.....");
    }

    @Override
    public void fly() {
        System.out.println("小鸟正在飞.....");
    }
}

老虎Tiger

// 老虎
public class Tiger implements IEat,ISwim {
    @Override
    public void eat() {
        System.out.println("老虎在吃鸡肉.....");
    }

    @Override
    public void swim() {
        System.out.println("老虎在游泳.....");
    }
}

这样来看,将eatswimfly三种方法拆分开来,分别放在三个不同的接口里,这样动物拥有哪几种习性就实现哪几个接口,不会再用空置的方法存在,这样看起来也简洁明了,来看看类图:

点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小    

二、迪米特法则

又被成为最少知道原则,指的是一个对象应该对其他对象保持最少的了解。一个实体类应当尽量少地和其他实体之间发生相互作用,使得系统模块相互独立。形象来说就是:只和朋友交流,不和陌生人说话

迪米特法则认为,一个对象或方法,它只能够调用以下对象:

- 该对象本身
- 作为参数传进来的对象
- 在方法内创建的对象

我们先来模拟一个超市购物的场景:顾客Customer到收银台结账,收银员PaperBoy负责收钱。

顾客的钱包Wallet

// 钱包
public class Wallet {

    // 钱包里装的钱
    private Float value;

    // 构造器
    public Wallet(Float value) {
        this.value = value;
    }

    // 获得钱包里的钱的金额
    public Float getMoney(){
        return this.value;
    }

    // 付账时 减钱
    public void reduceMoney(Float money){
        this.value -= money;
    }
}

顾客Customer

// 顾客
public class Customer {

    private Wallet wallet = new Wallet(50f);

    public Wallet getWallet() {
        return wallet;
    }
}

收银员PaperBoy

// 收银员
public class PaperBoy {

    // 收银员收钱
    public void charge(Customer customer,Float money){
        Wallet wallet = customer.getWallet();
        if (wallet.getMoney() ]= money){
            System.out.println("顾客付账:" + money +"元");
            // 减去 应付的钱
            wallet.reduceMoney(money);
            System.out.println("钱包里还剩:"+wallet.getMoney()+"元");
        } else {
            System.out.println("钱包里的金额不够......");
        }
    }
}

测试、运行

// 测试
public static void main(String[] args) {
    PaperBoy paperBoy = new PaperBoy();
    Customer customer = new Customer();
    paperBoy.charge(customer,20f);
}

点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

从测试代码和运行的结果来看,好像并没有什么问题。让我们来看一下类图:

点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

从类图中我们发现:PaperBoy类与Wallet类有着千丝万缕的关系,顾客(Customer)的钱包(Wallet)好像并不是自己来控制的,而是由收银员(PaperBoy)来决定的,就连钱包(Wallet)里面的钱够不够也是由收银员(PaperBoy)来判断的;相当于顾客(Customer)将自己的钱包(Wallet)暴露给了收银(PaperBoy),这样来看,问题就很严重了,顾客(Customer)的隐私受到了侵犯,说大点就是民事纠纷,是可以上法庭的,可以通过法律追究责任的。所以我们思考良久,将上述代码改成下面这般:

钱包Wallet类不变顾客Customer去掉给出钱包的getWallet()方法,增加付钱的pay()方法

// 顾客
public class Customer {

    private Wallet wallet = new Wallet(50f);

    // 顾客自己付钱
    public void pay(Float money){
        if (wallet.getMoney() ]= money){
            System.out.println("顾客付账:" + money +"元");
            // 减去 应付的钱
            wallet.reduceMoney(money);
            System.out.println("钱包里还剩:"+wallet.getMoney()+"元");
        } else {
            System.out.println("钱包里的金额不够......");
        }
    }
}

收银员PaperBoy类中的charge()方法中的代码删除原有的逻辑,改为调用顾客Customer类中的付钱pay()方法

// 收银员
public class PaperBoy {

    // 收银员收钱
    public void charge(Customer customer,Float money){
        customer.pay(money);
    }
}

测试代码不变,我们再来看看类图:

点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

从类的结构图来看:收银员PaperBoy只和顾客Customer有联系,钱包Wallet只和顾客Customer有联系。再此情况下,如果把钱包Wallet也当作一个人来看的话,这个就是如下的关系:

- 顾客Customer和钱包Wallet是朋友
- 顾客Customer和收银员PaperBoy是朋友
- 钱包Wallet和收银员PaperBoy是陌生人

这个就符合我们所说的迪米特法则中的核心:只和朋友交流,不和陌生人说话
            
        
    
    
----------------------------
原文链接:https://blog.51cto.com/caimm/2884384

程序猿的技术大观园:www.javathinker.net



[这个贴子最后由 flybird 在 2021-06-20 23:49:06 重新编辑]
  Java面向对象编程-->Swing组件(上)
  JavaWeb开发-->使用Session(Ⅰ)
  JSP与Hibernate开发-->映射对象标识符
  Java网络编程-->Java网络编程入门
  精通Spring-->绑定CSS样式
  Vue3开发-->Vue组件开发高级技术
  ThreadLocal的内存泄露的原因分析以及如何避免
  用VisualVM远程监控Java进程
  Java虚拟机(JVM)参数配置说明
  好消息:孙卫琴老师等直播分享Java分布式架构专题
  使用 RocketMQ 事务消息,实现分布事务
  Java并发编程之验证volatile不能保证原子性
  最实用的10个重构小技巧排行榜,你都用过哪些?
  分布式锁的原理和实现
  Java中的受查异常与非受查异常区别
  超详细的Java运算符修炼手册(优秀程序员不得不知道的运算技...
  Socket服务器的整体架构
  正则表达式性能调优
  Java入门实用代码:修改文件最后的修改日期
  正则表达式【匹配非字母和数字】
  Java中的main()方法详解
  更多...
 IPIP: 已设置保密
树形列表:   
小明家附近新开了一家动物园,里面有老虎、鸟儿、长颈鹿... amelinda 2023-09-05 09:54:34
1页 1条记录 当前第1
发表一个新主题 开启一个新投票 回复文章


中文版权所有: JavaThinker技术网站 Copyright 2016-2026 沪ICP备16029593号-2
荟萃Java程序员智慧的结晶,分享交流Java前沿技术。  联系我们
如有技术文章涉及侵权,请与本站管理员联系。