001-从零学习设计模式-设计原则

写在最前

文档地址:Wiki - Gitee.com

设计模式

推荐浏览:软件设计模式

  • 代表了代码的最佳实践,被有经验的开发人员所使用;

  • 设计模式是很多被反复使用并知晓的,主要是对代码和经验的总结;

  • 使用设计模式是为了重用代码,让代码更容易被他人理解,保证代码的可靠性;

  • 对接口编程而不是对实现变成;

  • 有限使用对象组合而不是继承关系;

设计原则

设计模式的六大设计(第七点为后增)原则通常是指的面向对象设计原则,也被称为SOLID原则。这六大设计原则分别是:

  1. 单一职责原则(Single Responsibility Principle,SRP):

    • 一个类应该只有一个引起变化的原因。这意味着一个类应该只有一个责任,只关注一个功能领域;

    • 降低程序的复杂度,提高程序可维护性,降低了变更所带来的风险;

  2. 开放/封闭原则(Open/Closed Principle,OCP):

    • 软件实体(类、模块、函数等)应该是可扩展的,但不可修改的。即,对于新增功能应通过扩展而不是修改现有代码来实现;

    • 使用抽象进行构建,使用实现扩展细节,面向抽象编程;

    • 提高软件系统的可复用性和可维护性;

  3. 里氏替换原则(Liskov Substitution Principle,LSP):

    • 所有引用基类的地方必须能够透明地使用其子类的对象,即子类可以替代基类而不影响程序的正确性;

    • 里氏替换原则是继承复用的基石,对开闭原则的补充;

    • 子类可以实现父类的抽象方法,但是不能覆盖原有父类的方法,子类中可以增加自己特有的方法;

    • 可以增加程序的健壮性;

  4. 接口隔离原则(Interface Segregation Principle,ISP):

    • 一个类对于它的客户端应该只暴露它们需要的方法,而不应该强迫客户端使用它们不需要的方法。接口应该是客户端特定的,而不是通用的;

    • 尽量细化接口,接口中的方法尽量少;

    • 符合低耦合的设计思想,提高了可扩展性和可维护性;

  5. 依赖倒置原则(Dependency Inversion Principle,DIP):

    • 高层模块不应该依赖于低层模块,而是两者都应该依赖于抽象。抽象不应该依赖于具体实现,而具体实现应该依赖于抽象;

    • 依赖倒置原则是开闭原则的基础,针对接口进行编程;

    • 可以减少类之间的耦合行,提高系统稳定性,提高代码可读性和可维护性;

    • 降低修改程序所造成的风险;

  6. 迪米特法则(Law of Demeter,LoD):

    • 一个对象应该对其他对象有最少的了解,即一个对象不应该直接调用另一个对象内部的方法,而应该通过一些中介者来进行间接调用;

    • 为了降低类与类之间的耦合关系;

    • 强调只和朋友交流,不和陌生人说话。朋友指的是成员变量或方法中输入输出的参数;

  7. 合成复用原则(Composite Reuse Principle,CRP):

    • 尽量使用对象组合,聚合的方式,而不是使用继承关系达到软件复用的目的;

    • 可以使系统更加灵活,降低类与类之间的耦合度,一个类的变化对其他类造成的影响相对较少;

这些设计原则共同为面向对象设计提供了指导方针,有助于创建更灵活、可维护和可扩展的代码。在应用这些原则时,设计模式通常被用来实现这些原则的具体设计方案。

单一职责原则

1.定义人类接口

人类都具有吃饭、睡觉的行为

public interface Human {
    /**
     * 吃饭
     */
    void eat();
​
    /**
     * 睡觉
     */
    void sleep();
}

2.定义程序员抽象类

程序员都需要工作

public abstract class Programmer implements Human {
    /**
     * 程序员都需要工作
     */
    abstract void work();
}

3.Java程序员

具备Java编写能力

public class JavaProgrammer extends Programmer {
    @Override
    public void eat() {
        System.out.println("Java程序员在吃饭");
    }
​
    @Override
    public void sleep() {
        System.out.println("Java程序员在睡觉");
    }
​
    @Override
    void work() {
        System.out.println("Java程序员在工作");
    }
​
    /**
     * Java程序员其他行为
     */
    void codeJava() {
        System.out.println("Java程序员在写Java代码");
    }
}

4.测试

public class Test {
    public static void main(String[] args) {
        JavaProgrammer javaProgrammer = new JavaProgrammer();
        javaProgrammer.codeJava();
        javaProgrammer.eat();
        javaProgrammer.work();
        javaProgrammer.sleep();
    }
}

开放/封闭原则

1.定义人类接口

人类都具有吃饭、睡觉的行为

public interface Human {
    /**
     * 吃饭
     */
    void eat();
​
    /**
     * 睡觉
     */
    void sleep();
}

2.学生实现人类接口

学生都具有学习的行为

public class Student implements Human {
    @Override
    public void eat() {
        System.out.println("学生在吃饭");
    }
​
    @Override
    public void sleep() {
        System.out.println("学生在睡觉");
    }
​
    public void study() {
        System.out.println("学生在学习");
    }
}

3.增加高中生

满足开闭原则,增加高中生,但不修改学生类。

public class HighSchoolStudent extends Student {
    @Override
    public void eat() {
        System.out.println("高中生在吃饭");
    }
​
    @Override
    public void sleep() {
        System.out.println("高中生在睡觉");
    }
​
    @Override
    public void study() {
        System.out.println("高中生在学习");
    }
​
    /**
     * 扩展高中生独有的属性或行为
     */
    public void doSomeThing() {
        System.out.println("高中生在谈恋爱");
    }
}

4.测试

public class Test {
    public static void main(String[] args) {
        Student student = new Student();
        student.eat();
        student.sleep();
        student.study();
​
        // 不修改学生类(对修改关闭),增加高中生(对扩展开发)
        HighSchoolStudent highSchoolStudent = new HighSchoolStudent();
        highSchoolStudent.eat();
        highSchoolStudent.sleep();
        highSchoolStudent.study();
        highSchoolStudent.doSomeThing();
    }
}

里氏替换原则

1.定义老鼠类

public class Mouse {
    void burrow() {
        System.out.println("老鼠会打洞。。。");
    }
}

2.定义仓鼠类继承老鼠

public class Hamster extends Mouse {
    // 子类可以不修改父类的方法,只是继承并使用 (老鼠天生会打洞)
}

3.定义玩具鼠类继承老鼠

public class ToyMouse extends Mouse {
    @Override
    void burrow() {
        // 它可以覆盖 burrow 方法,但不应该修改已经存在的行为
        System.out.println("我是玩具鼠,我不会打洞,我会上天");
    }
}

4.测试

public class Test {
    public static void main(String[] args) {
        Hamster hamster = new Hamster();
        // 老鼠生的会打洞
        hamster.burrow();
​
        ToyMouse toyMouse = new ToyMouse();
        // 老鼠生的不会打洞,会上天,就违背了该原则
        toyMouse.burrow();
    }
}

接口隔离原则

1.定义人类接口

public interface Human {}

2.人类行为拆分接口,进行接口隔离

吃饭

public interface EatAction extends Human {
    void eat();
}

睡觉

public interface SleepAction extends Human {
    void sleep();
}

3.学生具备吃饭、睡觉的行为

public class Student implements EatAction, SleepAction {
    @Override
    public void eat() {
        System.out.println("学生在吃饭");
    }
​
    @Override
    public void sleep() {
        System.out.println("学生在睡觉");
    }
}

4.测试

public class Test {
    public static void main(String[] args) {
        Student student = new Student();
​
        student.eat();
        student.sleep();
    }
}

依赖倒置原则

1.定义人类接口

人类都具有吃饭、睡觉的行为

public interface Human {
    /**
     * 吃饭
     */
    void eat();
​
    /**
     * 睡觉
     */
    void sleep();
}

2.定义程序员抽象类

public abstract class Programmer implements Human {
​
    @Override
    public void eat() {
        System.out.println("程序员在吃饭");
    }
​
    @Override
    public void sleep() {
        System.out.println("程序员在睡觉");
    }
​
    /**
     * 程序员都需要工作
     */
    abstract void work();
}

定义Java程序员、测试程序员

Java程序员

public class JavaProgrammer extends Programmer {
    @Override
    public void eat() {
        System.out.println("Java程序员在吃饭");
    }
​
    @Override
    public void sleep() {
        System.out.println("Java程序员在睡觉");
    }
​
    @Override
    void work() {
        System.out.println("Java程序员在工作");
    }
}

测试程序员

public class TestProgrammer extends Programmer {
    @Override
    public void eat() {
        System.out.println("测试程序员在吃饭");
    }
​
    @Override
    public void sleep() {
        System.out.println("测试程序员在睡觉");
    }
​
    @Override
    void work() {
        System.out.println("测试程序员在工作");
    }
}

4.测试

public class Test {
    public static void main(String[] args) {
        JavaProgrammer javaProgrammer = new JavaProgrammer();
        javaProgrammer.eat();
        javaProgrammer.work();
        javaProgrammer.sleep();
​
        TestProgrammer testProgrammer = new TestProgrammer();
        testProgrammer.work();
    }
}

迪米特法则

1.定义人类接口

public interface Human {}

2.定义管理层接口并实现

public interface Manager extends Human {}

公司老板

public class Boss implements Manager {
    public void meet(TeamLeader teamLeader) {
        System.out.println("老板开会,发布任务");
        teamLeader.assignTasks();
    }
}

团队领导

public class TeamLeader implements Manager {
​
    private Programmer programmer;
​
    public void setProgrammer(Programmer programmer) {
        this.programmer = programmer;
    }
​
    public void assignTasks() {
        System.out.println("团队领导给研发分配任务");
​
        this.programmer.work();
    }
}

3.定义程序员接口并实现

public abstract class Programmer implements Human {
    /**
     * 程序员都需要工作
     */
    abstract void work();
}

Java程序员

public class JavaProgrammer extends Programmer {
​
    @Override
    void work() {
        System.out.println("Java程序员完成Java代码开发");
    }
}

4.测试

public class Test {
    public static void main(String[] args) {
        // 老板准备发布任务
        Boss boss = new Boss();
​
        // 找到项目经理
        TeamLeader teamLeader = new TeamLeader();
​
        // 项目经理拉上手底下研发
        JavaProgrammer javaProgrammer = new JavaProgrammer();
        teamLeader.setProgrammer(javaProgrammer);
​
        // 老板发布任务
        boss.meet(teamLeader);
    }
}

合成复用原则

1.定义汽车引擎

public class Engine {
    void start() {
        System.out.println("发动机正在启动");
    }
}

2.定义汽车

public class Car {
    private Engine engine;
​
    Car(Engine engine) {
        this.engine = engine;
    }
​
    void start() {
        engine.start();
        System.out.println("汽车正在启动");
    }
}

3.测试

public class Test {
    public static void main(String[] args) {
        // 在传统的继承方式下,可能会让Car继承自Engine,但这样的设计可能导致不必要的耦合,违反了合成复用原则。
        Engine engine = new Engine();
        // 使用合成复用原则通过组合来实现复用。
        Car car = new Car(engine);
        car.start();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Strive_MY

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值