ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java设计模式(3:接口隔离原则和迪米特法则详解)

2021-06-09 11:57:40  阅读:171  来源: 互联网

标签:Customer Java void System 接口隔离 Wallet println 设计模式 public


#### 一、接口隔离原则 > 使用多个接口,而不使用单一的接口,客户端不应该依赖它不需要的接口。尽量的**细化接口的职责,降低类的耦合度**。 我们先来看一个例子: > 小明家附近新开了一家动物园,里面有老虎、鸟儿、长颈鹿.....周末在逛动物园的时候,小明突发奇想,想用一种方式记录一下这些动物的习性,于是他将老虎和鸟儿的习性结合了一下,写了下面这段代码: **动物行为** ```java // 动物行为 public interface Animal { // 吃 public void eat(); // 游泳 public void swim(); // 飞 public void fly(); } ``` **老虎`Tiger`** ```java // 老虎 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`** ```java // 小鸟 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`类都会空置一个方法,对于代码的结构设计来说不太合理。于是,他划掉了上面的三段代码,仔细思索了一会儿,写出了下面这几段代码: ```java // 游泳 public interface ISwim { public void swim(); } // 吃 public interface IEat { public void eat(); } // 飞 public interface IFly { public void fly(); } ``` **小鸟`Bird`** ```java // 小鸟 public class Brid implements IEat,IFly { @Override public void eat() { System.out.println("小鸟在吃虫子....."); } @Override public void fly() { System.out.println("小鸟正在飞....."); } } ``` **老虎`Tiger`** ```JAVA // 老虎 public class Tiger implements IEat,ISwim { @Override public void eat() { System.out.println("老虎在吃鸡肉....."); } @Override public void swim() { System.out.println("老虎在游泳....."); } } ``` > 这样来看,将`eat`、`swim`、`fly`三种方法拆分开来,分别放在三个不同的接口里,这样动物拥有哪几种习性就实现哪几个接口,不会再用空置的方法存在,这样看起来也简洁明了,来看看类图: ![](http://www.icode9.com/i/li/?n=4&i=images/blog/202106/09/59a32c98d4bd592f107197a7653acb10.png?,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=) #### 二、迪米特法则 > 又被成为**最少知道原则**,指的是一个对象应该对其他对象保持最少的了解。一个实体类应当尽量少地和其他实体之间发生相互作用,使得系统模块相互独立。形象来说就是:**只和朋友交流,不和陌生人说话**。 **迪米特法则**认为,一个对象或方法,它只能够调用以下对象: - 该对象本身 - 作为参数传进来的对象 - 在方法内创建的对象 我们先来模拟一个超市购物的场景:顾客`Customer`到收银台结账,收银员`PaperBoy`负责收钱。 **顾客的钱包`Wallet`** ```java // 钱包 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`** ```java // 顾客 public class Customer { private Wallet wallet = new Wallet(50f); public Wallet getWallet() { return wallet; } } ``` **收银员`PaperBoy`** ```java // 收银员 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("钱包里的金额不够......"); } } } ``` **测试、运行** ```java // 测试 public static void main(String[] args) { PaperBoy paperBoy = new PaperBoy(); Customer customer = new Customer(); paperBoy.charge(customer,20f); } ``` ![](http://www.icode9.com/i/li/?n=4&i=images/blog/202106/09/4e9418259a98efe2ae49ad997813dd54.png?,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=) 从测试代码和运行的结果来看,好像并没有什么问题。让我们来看一下类图: ![](http://www.icode9.com/i/li/?n=4&i=images/blog/202106/09/6babb74700f2227bb4168df7050dc88e.png?,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=) 从类图中我们发现:`PaperBoy`类与`Wallet`类有着千丝万缕的关系,顾客(`Customer`)的钱包(`Wallet`)好像并不是自己来控制的,而是由收银员(`PaperBoy`)来决定的,就连钱包(`Wallet`)里面的钱够不够也是由收银员(`PaperBoy`)来判断的;相当于顾客(`Customer`)将自己的钱包(`Wallet`)暴露给了收银(`PaperBoy`),这样来看,问题就很严重了,顾客(`Customer`)的隐私受到了侵犯,说大点就是民事纠纷,是可以上法庭的,可以通过法律追究责任的。所以我们思考良久,将上述代码改成下面这般: **钱包`Wallet`类不变**,**顾客`Customer`去掉给出钱包的`getWallet()`方法,增加付钱的`pay()`方法**: ```java // 顾客 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()`方法**: ```java // 收银员 public class PaperBoy { // 收银员收钱 public void charge(Customer customer,Float money){ customer.pay(money); } } ``` **测试代码不变**,我们再来看看类图: ![](http://www.icode9.com/i/li/?n=4&i=images/blog/202106/09/8db4f37a3f166e5f9a0dad54fd11c6a0.png?,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=) 从类的结构图来看:收银员`PaperBoy`只和顾客`Customer`有联系,钱包`Wallet`只和顾客`Customer`有联系。再此情况下,如果把钱包`Wallet`也当作一个人来看的话,这个就是如下的关系: - 顾客`Customer`和钱包`Wallet`是朋友 - 顾客`Customer`和收银员`PaperBoy`是朋友 - 钱包`Wallet`和收银员`PaperBoy`是陌生人 这个就符合我们所说的**迪米特法则**中的核心:**只和朋友交流,不和陌生人说话**。

标签:Customer,Java,void,System,接口隔离,Wallet,println,设计模式,public
来源: https://blog.51cto.com/u_14229555/2884384

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有