Java设计模式6大原则(下)

简介: 设计模式的6大原则,单一职责原则,开放封闭原则,里式替换原则,依赖导致原则,迪米特原则和接口隔离原则。

依赖倒置原则

高层模块(调用端)不应该依赖底层模块,两者都应该依赖于抽象。抽象不应该依赖于细节(实现类),细节应该依赖于抽象。


在Java中,抽象指接口或者抽象类,两者都是不能直接被实例化;细节就是实现类,实现接口或者继承抽象类而产生的就是细节,也就是可以加上一个关键字 new 产生的对象。高层模块就是调用端,低层模块就是具体实现类。 依赖倒置原则在 java 中的表现就是,模块间的依赖通过抽象发生,实现类之间不发生直接依赖关系,其依赖关系就是通过接口或者抽象类产生的。如果类与类直接依赖细节,那么就会直接耦合。如此一来,就会同时修改依赖者代码,这样限制了可扩展性。

class Cat {
    void Cry() {
        System.out.println("喵喵");
    }
}
class Dog {
    void Cry() {
        System.out.println("旺旺");
    }
}
class Animal {
    void Cry(Cat cat, Dog dog) {
        cat.Cry();
        dog.Cry();
    }
}
class Test{
    public static void main(String[] args) {
        new Animal().Cry(new Cat(),new Dog());
    }
}

上面这个代码看起来没什么问题,可是如果我们还有别的动物子类时,就又要去更改 Animal类,将其对象作为参数传入Cry方法。而依赖倒置原则 模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系。而我们上面这个Demo已经违背了这个原则,下面我们对它进行修改。

interface Dongwu{
    void Cry();
}
class Cat implements Dongwu{
    public void Cry() {
        System.out.println("喵喵");
    }
}
class Dog implements Dongwu{
    public void Cry() {
        System.out.println("旺旺");
    }
}
class Animal {
    Dongwu dongwu;
    public void setDongwu(Dongwu dongwu) {
        this.dongwu = dongwu;
    }
    void Cry() {
       dongwu.Cry();
    }
}
class Test{
    public static void main(String[] args) {
        Animal animal=new Animal();
        animal.setDongwu(new Dog());
        animal.Cry();
        animal.setDongwu(new Cat());
        animal.Cry();
    }
}

我们增加了一个接口,里面有一个动物的叫声方法,然后让动物类们实现这个接口,然后通过set方法传递依赖对象,这样,如果我们再新增别的动物类,只需要实现相应的接口,而无需再更改我们的管理类 Animal。

迪米特原则

一个软件实体应当少的与其他实体发生相互作用。

这也被称最好知识原则。如果一个系统符合迪米特原则,那么当其中某一个模块发生修改时,就会尽量少的影响其他模块。迪米特原则要求我们在设计系统是,应该尽量减少对象之间的交互。如果两个对象之间不必彼此直接通向,那么这两个对象就不应当发生任何直接的相互作用。如果其中的一个对象需要调用另一个对象的某一个方法,则可以通过第三者转发这个调用。简言之,就是通过引入一个合理的第三者来降低现有对象之间的耦合度。在将迪米特原则运用到系统设计中时,要注意以下几点:

  • 在类的划分上,应当尽量创建松耦合的类。类之间的耦合越低,就越有利于复用。一个处在松耦合中的类一旦被修改,则不会对关联的类造成太大波及。
  • 在类的结构上,每一个类都应当尽量降低其成员变量和成员函数的访问权限。
  • 在对其他类的引用上,一个对象对其他对象的引用应当降到最低。


举个例子


就像租房子一样,我叫老王,准备租房子,然后找中介,中介和房东谈价格,我们和中介谈价格,如果我们想自己和房东联系,这种事情肯定是要通过中介介绍了,或者别的途径。

Demo如下

//租房者:老王类
//inform 通知方法
class LaoWang {
    private Zhongjie zhongjie;
    public Zhongjie getZhongjie(){
        return zhongjie;
    }
    public void setZhongjie(Zhongjie zhongjie) {
        this.zhongjie = zhongjie;
    }
    public void inform(){
        zhongjie.inform();
    }
}
//中介类
//inform 通知方法
//setLandlord 接收房东消息
class Zhongjie{
    public void inform(){
        System.out.println("通知房东");
    }
    public   void getLanged(){
        new Landlord().inform();
    }
}
//房东类
//inform 通知方法
class Landlord{
    public void inform(){
        System.out.println("收到,可以租");
    }
}
class Renting{
    public static void main(String[] args) {
        LaoWang laoWang=new LaoWang();
        //老王通知中介
        laoWang.inform();
        //传入房东对象
        laoWang.setZhongjie(new Zhongjie());
        //由中介去通知房东
        laoWang.getZhongjie().inform();
        //接收房东消息
        laoWang.getZhongjie().getLanged();
    }
} 

这样,老王和房东之间就没有任何联系,避免了耦合度过高。

我们还可以将上面的Demo再次更改,相当和依赖倒转原则结合。因为一般租房会看好多房子,所以房东也各不相同,这时候就可以将房东抽成一个抽象类,具体的房东实现房东抽象方法即可,这样的方式,和老王通信的就是房东的抽象父类,和具体房东没有关系。

public abstract class Lease {
    abstract void inform();
}
//租房者:老王类
//inform 通知方法
class LaoWang {
    private Zhongjie zhongjie;
    private Lease lease;
    public void setLease(Lease lease) {
        this.lease = lease;
    }
    public void setZhongjie(Zhongjie zhongjie) {
        this.zhongjie = zhongjie;
    }
    public void inform() {
        zhongjie.inform();
        lease.inform();
    }
}
//中介类
//inform 通知方法
class Zhongjie {
    public void inform() {
        System.out.println("通知房东");
    }
}
//Landlord_X 房东X
//inform 通知方法
class Landlord_X extends Lease {
    public void inform() {
        System.out.println("收到,可以租");
    }
}
class Renting{
    public static void main(String[] args) {
        LaoWang laoWang=new LaoWang();
        laoWang.setLease(new Landlord_X());
        laoWang.setZhongjie(new Zhongjie());
        laoWang.inform();
    }
}

接口隔离原则

一个类对另一个类的依赖应该建立在最小的接口上

建立单一接口,不要建立庞大臃肿的接口:尽量细化接口,接口中的方法尽量少。也就是说,我们要为各个类建立专用的接口,而不要试图建立一个一个很庞大的接口供所有依赖他的类调用。采取接口隔离原则对接口进行约束时,要注意以下几点:

接口尽量小,但是要有限度。对接口进行细化可以提高程序设计的灵活性;但是如果过小,则会造成接口数量过多,使设计复杂化。所以,一定要适度。

为依赖接口的类定制服务,只暴露给调用的类他需要的方法,他不需要的方法则隐藏起来,只有专注的为一个模块提供定制服务,才能建立最小的依赖关系。

为提高内聚,减少对外交互。接口方法尽量少用public 修饰。接口是对外的承诺,承诺越少对系统的开发越有利,变更的风险也越少。


Demo

//color 颜色
//taste 口感
//hardness 硬度
// small气味
interface Frits {
    void color();
    void taste();
    void hardness();
    void small();
}
 class apple implements Frits{
     @Override
     public void color() {
     }
     @Override
     public void taste() {
     }
     @Override
     public void hardness() {
     }
     @Override
     public void small() {
     }
 }

定义了一个水果接口,里面有水果的各项方法,如果我们还有别的方法,那么这个接口必然会受到多次修改。所以我们可以对其进行分隔,比如外观为一类,内在为一类,结果如下

//Facade 外观
interface Facade {
     void color();
     void hardness();
}
//Inherent 内在
interface Inherent {
    void taste();
    void small();
}
class banana implements Facade,Inherent{
    @Override
    public void taste() {
    }
    @Override
    public void small() {
    }
    @Override
    public void color() {
    }
    @Override
    public void hardness() {
    }
}

接口是我们设计时对外提供的契约,通过分散定义多个 接口,可以预防未来变更的扩散,提高系统的灵活性和可维护性。

目录
相关文章
|
4月前
|
设计模式 Java Spring
Java 设计模式之责任链模式:优雅处理请求的艺术
责任链模式通过构建处理者链,使请求沿链传递直至被处理,实现发送者与接收者的解耦。适用于审批流程、日志处理等多级处理场景,提升系统灵活性与可扩展性。
545 2
|
4月前
|
设计模式 网络协议 数据可视化
Java 设计模式之状态模式:让对象的行为随状态优雅变化
状态模式通过封装对象的状态,使行为随状态变化而改变。以订单为例,将待支付、已支付等状态独立成类,消除冗长条件判断,提升代码可维护性与扩展性,适用于状态多、转换复杂的场景。
479 0
|
6月前
|
设计模式 缓存 Java
Java设计模式(二):观察者模式与装饰器模式
本文深入讲解观察者模式与装饰器模式的核心概念及实现方式,涵盖从基础理论到实战应用的全面内容。观察者模式实现对象间松耦合通信,适用于事件通知机制;装饰器模式通过组合方式动态扩展对象功能,避免子类爆炸。文章通过Java示例展示两者在GUI、IO流、Web中间件等场景的应用,并提供常见陷阱与面试高频问题解析,助你写出灵活、可维护的代码。
|
4月前
|
设计模式 算法 搜索推荐
Java 设计模式之策略模式:灵活切换算法的艺术
策略模式通过封装不同算法并实现灵活切换,将算法与使用解耦。以支付为例,微信、支付宝等支付方式作为独立策略,购物车根据选择调用对应支付逻辑,提升代码可维护性与扩展性,避免冗长条件判断,符合开闭原则。
805 35
|
4月前
|
设计模式 消息中间件 传感器
Java 设计模式之观察者模式:构建松耦合的事件响应系统
观察者模式是Java中常用的行为型设计模式,用于构建松耦合的事件响应系统。当一个对象状态改变时,所有依赖它的观察者将自动收到通知并更新。该模式通过抽象耦合实现发布-订阅机制,广泛应用于GUI事件处理、消息通知、数据监控等场景,具有良好的可扩展性和维护性。
429 8
|
9月前
|
设计模式 缓存 安全
【高薪程序员必看】万字长文拆解Java并发编程!(8):设计模式-享元模式设计指南
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发编程中的经典对象复用设计模式-享元模式,废话不多说让我们直接开始。
201 0
|
6月前
|
设计模式 安全 Java
Java设计模式(一):单例模式与工厂模式
本文详解单例模式与工厂模式的核心实现及应用,涵盖饿汉式、懒汉式、双重检查锁、工厂方法、抽象工厂等设计模式,并结合数据库连接池与支付系统实战案例,助你掌握设计模式精髓,提升代码专业性与可维护性。
|
6月前
|
设计模式 XML 安全
Java枚举(Enum)与设计模式应用
Java枚举不仅是类型安全的常量,还具备面向对象能力,可添加属性与方法,实现接口。通过枚举能优雅实现单例、策略、状态等设计模式,具备线程安全、序列化安全等特性,是编写高效、安全代码的利器。
|
11月前
|
设计模式 Java 数据安全/隐私保护
Java 设计模式:装饰者模式(Decorator Pattern)
装饰者模式属于结构型设计模式,允许通过动态包装对象的方式为对象添加新功能,提供比继承更灵活的扩展方式。该模式通过组合替代继承,遵循开闭原则(对扩展开放,对修改关闭)。
|
12月前
|
设计模式 架构师 Java
设计模式觉醒系列(01)设计模式的基石 | 六大原则的核心是什么?
本文介绍了设计模式的六大原则,包括单一职责原则(SRP)、开闭原则(OCP)、里氏替换原则(LSP)、接口隔离原则(ISP)、依赖倒置原则(DIP)和迪米特法则。通过具体案例分析了每个原则的应用场景及优势,强调了这些原则在提升代码可维护性、可复用性、可扩展性和降低耦合度方面的重要作用。文章指出,设计模式的核心在于确保系统模块间的低耦合高内聚,并为后续深入探讨23个经典设计模式打下基础。

热门文章

最新文章