1.七大原则

本文详细介绍了设计模式的七大原则,包括单一职责原则、接口隔离原则、依赖倒转原则、里氏替换原则、开闭原则、狄米特法则和合成复用法则。通过实例分析,阐述了每个原则的核心思想及其在实际编程中的应用,旨在提高软件的可维护性和扩展性。
摘要由CSDN通过智能技术生成

设计模式七大原则;

  1. 单一职责原则
  2. 接口隔离原则
  3. 依赖倒转(倒置)原则
  4. 里氏替换原则
  5. 开闭原则
  6. 狄米特法则
  7. 合成复用法则

介绍:

下述案例来自大佬:https://zhuanlan.zhihu.com/p/24614363

(1).单一职责

介绍:对类来说,一个类应该负责一项职责,如果A负责两个不同的职责1、职责2,当职责1的需求变更改变A时,可能造成职责2执行错误,所以需要将类A的粒度分解为A1,A2

class Animal{  
    public void breathe(String animal){  
        System.out.println(animal + "呼吸空气");  
    }  
  
    public void breathe2(String animal){  
        System.out.println(animal + "呼吸水");  
    }  
}  
  
public class Client{  
    public static void main(String[] args){  
        Animal animal = new Animal();  
        animal.breathe("牛");  
        animal.breathe("羊");  
        animal.breathe("猪");  
        animal.breathe2("鱼");  
    }  
}  

(2).接口隔离原则 ISP

客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。

如果是这种实现方式

interface I {  
    public void method1();  
    public void method2();  
    public void method3();  
    public void method4();  
    public void method5();  
}  
  
class A{  
    public void depend1(I i){  
        i.method1();  
    }  
    public void depend2(I i){  
        i.method2();  
    }  
    public void depend3(I i){  
        i.method3();  
    }  
}  
  
class B implements I{  
	 // 类 B 只需要实现方法 1,2, 3,而其它方法它并不需要,但是也需要实现
    public void method1() {  
        System.out.println("类 B 实现接口 I 的方法 1");  
    }  
    public void method2() {  
        System.out.println("类 B 实现接口 I 的方法 2");  
    }  
    public void method3() {  
        System.out.println("类 B 实现接口 I 的方法 3");  
    }  
    public void method4() {}  
    public void method5() {}  
}  
  
class C{  
    public void depend1(I i){  
        i.method1();  
    }  
    public void depend2(I i){  
        i.method4();  
    }  
    public void depend3(I i){  
        i.method5();  
    }  
}
class D implements I{  
	// 类 D 只需要实现方法 1,4,5,而其它方法它并不需要,但是也需要实现
    public void method1() {  
        System.out.println("类 D 实现接口 I 的方法 1");  
    }  
    public void method2() {}  
    public void method3() {}  
    public void method4() {  
        System.out.println("类 D 实现接口 I 的方法 4");  
    }  
    public void method5() {  
        System.out.println("类 D 实现接口 I 的方法 5");  
    }  
}  
  
public class Client{  
    public static void main(String[] args){  
        A a = new A();  
        a.depend1(new B());  
        a.depend2(new B());  
        a.depend3(new B());  
          
        C c = new C();  
        c.depend1(new D());  
        c.depend2(new D());  
        c.depend3(new D());  
    }  
}  

缺点:可以看出,如果接口定义的过于臃肿,只要接口中出现的方法,不管依赖于它的类是否需要该方法,实现类都必须去实现这些方法,这就不符合接口隔离原则

interface I1 {  
    public void method1();  
}  
  
interface I2 {  
    public void method2();  
    public void method3();  
}  
  
interface I3 {  
    public void method4();  
    public void method5();  
}  
  
class A{  
    public void depend1(I1 i){  
        i.method1();  
    }  
    public void depend2(I2 i){  
        i.method2();  
    }  
    public void depend3(I2 i){  
        i.method3();  
    }  
}  
  
class B implements I1, I2{  
    public void method1() {  
        System.out.println("类 B 实现接口 I1 的方法 1");  
    }  
    public void method2() {  
        System.out.println("类 B 实现接口 I2 的方法 2");  
    }  
    public void method3() {  
        System.out.println("类 B 实现接口 I2 的方法 3");  
    }  
}  
  
class C{  
    public void depend1(I1 i){  
        i.method1();  
    }  
    public void depend2(I3 i){  
        i.method4();  
    }  
    public void depend3(I3 i){  
        i.method5();  
    }  
}  
  
class D implements I1, I3{  
    public void method1() {  
        System.out.println("类 D 实现接口 I1 的方法 1");  
    }  
    public void method4() {  
        System.out.println("类 D 实现接口 I3 的方法 4");  
    }  
    public void method5() {  
        System.out.println("类 D 实现接口 I3 的方法 5");  
    }  
}  
  1. 接口隔离原则的思想在于建立单一接口,尽可能地去细化接口,接口中的方法尽可能少
  2. 但是凡事都要有个度,如果接口设计过小,则会造成接口数量过多,使设计复杂化。所以一定要适度。

(3)依赖倒转原则

高层模块不应该依赖低层模块,二者都应该于抽象。进一步说,抽象不应该依赖于细节,细节应该依赖于抽象。依赖倒转原则的核心是面向接口编程

思考下面这样一个场景:母亲给孩子讲故事,只要给她一本书,她就可照着书给孩子讲故事了。代码如下:

class Book{  
    public String getContent(){  
        return "这是一个有趣的故事";  
    }  
}  
  
class Mother{  
    public void say(Book book){  
        System.out.println("妈妈开始讲故事");  
        System.out.println(book.getContent());  
    }  
}  
  
public class Client{  
    public static void main(String[] args){  
        Mother mother = new Mother();  
        mother.say(new Book());  
    }  
}  

假如有一天,给的是一份报纸,而不是一本书,让这个母亲讲下报纸上的故事,报纸的代码如下:

class Newspaper{  
    public String getContent(){  
        return "这个一则重要的新闻";  
    }  
}  

然而这个母亲却办不到,应该她只会读书,这太不可思议,只是将书换成报纸,居然需要修改 Mother 类才能读,假如以后需要换成了杂志呢?原因是 Mother 和 Book 之间的耦合度太高了,必须降低他们的耦合度才行。

我们可以引入一个抽象接口 IReader 读物,让书和报纸去实现这个接口,那么无论提供什么样的读物,该母亲都能读。代码如下:

interface IReader{  
    public String getContent();  
}  

class Newspaper implements IReader {  
    public String getContent(){  
        return "这个一则重要的新闻";  
    }  
}  
class Book implements IReader{  
    public String getContent(){  
        return "这是一个有趣的故事";  
    }  
}  
  
class Mother{  
    public void say(IReader reader){  
        System.out.println("妈妈开始讲故事");  
        System.out.println(reader.getContent());  
    }  
}  
  
public class Client{  
    public static void main(String[] args){  
        Mother mother = new Mother();  
        mother.say(new Book());  
        mother.say(new Newspaper());  
    }  
}

这样修改之后,以后无论提供什么样的读物,只要去实现了 IReader 接口之后就可以被母亲读。实际情况中,代表高层模块的 Mother 类将负责完成主要的业务逻辑,一旦需要对它进行修改,引入错误的风险极大。所以遵循依赖倒转原则可以降低类之间的耦合性,提高系统的稳定性,降低修改程序造成的风险。

(4)里氏替换原则

里氏替换原则的重点在不影响原功能,而不是不覆盖原方法

父类中凡是已经实现好的方法(相对于抽象方法而言),实际上是在设定一系列的规范和契约,虽然它不强制要求所有的子类必须遵从这些契约,但是如果子类对这些非抽象方法任意修改,就会对整个继承体系造成破坏。而里氏替换原则就是表达了这一层含义

(5)开闭原则

  • 1.开闭原则是编程中最重要、最基础的设计原则
  • 2.一个软件实体如类,模块和函数应该对扩展开放,对修改关闭,用抽象构建框架,用实现设计细节;
  • 3.软件需要变化的时候,尽量通过扩展软件实体的行为来实现变化,而不是修改已有的代码,
  • 4.编程中遵循其他原则,以及使用设计模式的目的就是遵循开闭原则

开放-关闭原则表示软件实体 (类、模块、函数等等) 应该是可以被扩展的,但是不可被修改;优点

  1. 能够扩展已存在的系统,能够提供新的功能满足新的需求,因此该软件有着很强的适应性和灵活性。
  2. 已存在的模块,特别是那些重要的抽象模块,不需要被修改,那么该软件就有很强的稳定性和持久性。

举个简单例子,这里有个生产电脑的公司,根据输入的类型,生产出不同的电脑,代码如下:

interface Computer {}
class Macbook implements Computer {}
class Surface implements Computer {}
class Factory {
    public Computer produceComputer(String type) {
        Computer c = null;
        if(type.equals("macbook")){
            c = new Macbook();
        }else if(type.equals("surface")){
            c = new Surface();
        }
        return c;
    }   
}

显然上面的代码违背了开放 - 关闭原则,如果需要添加新的电脑产品,那么修改 produceComputer 原本已有的方法,正确的方式如下:

interface Computer {}
class Macbook implements Computer {}
class Surface implements Computer {}
interface Factory {
    public Computer produceComputer();
}
class AppleFactory implements Factory {
    public Computer produceComputer() {
        return new Macbook();
    }
}
class MSFactory implements Factory {
    public Computer produceComputer() {
        return new Surface();
    }
}

正确的方式应该是将 Factory 抽象成接口,让具体的工厂(如苹果工厂,微软工厂)去实现它,生产它们公司相应的产品,这样写有利于扩展,如果这是需要新增加戴尔工厂生产戴尔电脑,我们仅仅需要创建新的电脑类和新的工厂类,而不需要去修改已经写好的代码。

(6)狄米特法则

迪米特法则又称为 最少知道原则,它表示一个对象应该对其它对象保持最少的了解。通俗来说就是,只与直接的朋友通信。

 

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值