实现类
package com.jsxs.principles.demo4.befor; /** * @Author Jsxs * @Date 2023/4/16 10:15 * @PackageName:com.jsxs.principles.demo4.befor * @ClassName: HeimaSaferDoor * @Description: TODO 实现类 * @Version 1.0 */ public class HeimaSaferDoor implements SafeDoor{ @Override public void antiTheft() { System.out.println("防盗"); } @Override public void fireProof() { System.out.println("防火"); } @Override public void waterProof() { System.out.println("防水"); } }
测试类
package com.jsxs.principles.demo4.befor; /** * @Author Jsxs * @Date 2023/4/16 10:17 * @PackageName:com.jsxs.principles.demo4.befor * @ClassName: SafeDoorTest * @Description: TODO * @Version 1.0 */ public class SafeDoorTest { public static void main(String[] args) { HeimaSaferDoor heimaSaferDoor = new HeimaSaferDoor(); heimaSaferDoor.antiTheft(); heimaSaferDoor.fireProof(); heimaSaferDoor.waterProof(); } }
上面的设计我们发现问题: 黑马品牌的安全门具有防盗、防火、防水的功能。现在如果我们还需要再创建一个传智品牌的安全们,而它只具有防盗、防水的功能。很显然我们这里设计的接口就违反了接口隔离原则,那么我们如何进行修改呢?
正列:
接口1
package com.jsxs.principles.demo4.after; /** * @Author Jsxs * @Date 2023/4/16 10:29 * @PackageName:com.jsxs.principles.demo4.after * @ClassName: fireProof * @Description: TODO * @Version 1.0 */ public interface fireProof { void fire(); }
接口2
package com.jsxs.principles.demo4.after; /** * @Author Jsxs * @Date 2023/4/16 10:29 * @PackageName:com.jsxs.principles.demo4.after * @ClassName: waterProof * @Description: TODO 防水 * @Version 1.0 */ public interface waterProof { void water(); }
接口三
package com.jsxs.principles.demo4.after; /** * @Author Jsxs * @Date 2023/4/16 10:30 * @PackageName:com.jsxs.principles.demo4.after * @ClassName: theafProof * @Description: TODO * @Version 1.0 */ public interface theafProof { void thymef(); }
黑马门
package com.jsxs.principles.demo4.after; /** * @Author Jsxs * @Date 2023/4/16 10:30 * @PackageName:com.jsxs.principles.demo4.after * @ClassName: HeimaDoor * @Description: TODO * @Version 1.0 */ public class HeimaDoor implements fireProof,waterProof{ @Override public void fire() { System.out.println("防火"); } @Override public void water() { System.out.println("防水"); } }
测试实验
package com.jsxs.principles.demo4.after; /** * @Author Jsxs * @Date 2023/4/16 10:31 * @PackageName:com.jsxs.principles.demo4.after * @ClassName: DoorTest * @Description: TODO * @Version 1.0 */ public class DoorTest { public static void main(String[] args) { HeimaDoor heimaDoor = new HeimaDoor(); heimaDoor.fire(); heimaDoor.water(); } }
(5).迪米特法则 (直接与间接)
迪米特法则又叫最少知识原则。
只和你的直接朋友交谈,不跟陌生人说话。 其含义是: 如果两个软件实体无需直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发调用
。其目的是降低类之间的耦合度,提高模块的相对独立开发。
迪米特法则中的 "朋友"是指: 当前对象本身、当前对象的成员对象、当前对象所创建的对象、当前对象的方法参数
等。这些兑现同当前对象存在关联、聚合或组合关系,可以直接访问这些对象的方法。
eg: 明星和经纪人的关系实列
明星由于全身心的投入艺术、所以很多的日常事务都是由经纪人负责处理的,比如粉丝的见面会和媒体公司的业务洽谈等。这里的经纪人是明星的朋友,而粉丝和媒体公司是明星的陌生人,所以适合使用迪米特法则。
明星
package com.jsxs.principles.demo5; /** * @Author Jsxs * @Date 2023/4/16 11:00 * @PackageName:com.jsxs.principles.demo5 * @ClassName: Star * @Description: TODO * @Version 1.0 */ public class Star { private String name; public Star(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
粉丝
package com.jsxs.principles.demo5; /** * @Author Jsxs * @Date 2023/4/16 11:01 * @PackageName:com.jsxs.principles.demo5 * @ClassName: Fans * @Description: TODO 粉丝类 * @Version 1.0 */ public class Fans { private String name; public Fans(String name) { this.name = name; } public String getName() { return name; } }
公司
package com.jsxs.principles.demo5; /** * @Author Jsxs * @Date 2023/4/16 11:02 * @PackageName:com.jsxs.principles.demo5 * @ClassName: Bussiness * @Description: TODO 媒体公司类 * @Version 1.0 */ public class Company { private String name; public Company(String name) { this.name = name; } public String getName() { return name; } }
经纪人
package com.jsxs.principles.demo5; /** * @Author Jsxs * @Date 2023/4/16 11:03 * @PackageName:com.jsxs.principles.demo5 * @ClassName: Agent * @Description: TODO 经纪人类 * @Version 1.0 */ public class Agent { private Star star; private Fans fans; private Company company; public void setStar(Star star) { this.star = star; } public void setFans(Fans fans) { this.fans = fans; } public void setCompany(Company company) { this.company = company; } // 1.和粉丝见面 public void meeting(){ System.out.println(star.getName()+"见面粉丝"+fans.getName()); } //2.和媒体公司洽谈 public void business(){ System.out.println(star.getName()+"洽谈公司"+company.getName()); } }
测试
package com.jsxs.principles.demo5; /** * @Author Jsxs * @Date 2023/4/16 11:06 * @PackageName:com.jsxs.principles.demo5 * @ClassName: StarTest * @Description: TODO * @Version 1.0 */ public class StarTest { public static void main(String[] args) { Fans fans = new Fans("李明"); Company company = new Company("CKQN"); Star star = new Star("及你太美"); Agent agent = new Agent(); agent.setStar(star); agent.setCompany(company); agent.setFans(fans); agent.business(); agent.meeting(); } }
(6).合成复用原则
合成复用原则是指: 尽量先使用组合或则和聚合等关系来实现,其次再开率使用继承关系来实现。
通常类的复用分为继承复用和合成复用两种。
继承复用虽然有简单和容易实现的优点,但它也存在以下缺点:
继承复用破坏了类的封装性
。因为继承会将父类的实现细节暴露给子类,父类对子类是透明的,所以这种复用又称为"白箱"复用
子类与父类的耦合度高
。父类的实现的任何改变都会导致子类的实现发生变化,这不利于类的扩展和维护
。它限制了复用的灵活性
。从子类继承而来的实现是静态的,在编译时已经定义,所以再运行时不可能发生变化。
采用组合或聚合复用时,可以将已有对象纳入新的对象中,使之称为对象的一部分,新对象可以调用已有对象的功能,它有以下的优点:
它维持了类的封装性
。因为成分对象的内部细节时新对象看不见的,所以这种服用又称为"黑箱"复用。对象的耦合度低
。可以在类的成员位置声明抽象。复用的灵活性高
。这种复用可以在运行时动态进行,新对象可以动态地引用与成分对象类型相同的对象。
汽车按动力源划分可分为汽油汽车、电动汽车;按"颜色"划分为白色汽车、黑色汽车和红色汽车等。如果同时看i哦率这两种分类,其组合就很多。类图如下:
继承复用: 假如新增填一个汽车动力、会牵扯到很多的子类
将继承复用更改为集合复用