Java中的7大设计原则

在面向对象的设计过程中,首先需要考虑的是如何同时提高一个软件系统的可维护性和可复用性。这时,遵从面向对象的设计原则,可以在进行设计方案时减少错误设计的产生,从不同的角度提升一个软件结构的设计水平。

1、单一职责

一个类尽可能只干一件事情。普通会员、vip会员、黄金会员三个类,各干自己的事。

优点:低耦合、高内聚。

2、开闭原则

对扩展开放,对修改关闭。(继承或多态)

不建议对原来的代码进行修改,可以扩展一个新的类,来实现功能。

对程序进行抽象化设计,设计出抽象类/接口,根据不同的功能来扩展子类。

class CarDemo{
    public static void main(String[] args) {
        new CarFactory().carfactory(new Aodi());
        new CarFactory().carfactory(new DaZhong());
    }
}

class CarFactory{
    void carfactory(Car car){
         car.createCar();
    }
}

abstract  class Car{
   public abstract void createCar();
}

class Aodi extends Car{
    @Override
    public void createCar() {
        System.out.println("造奥迪汽车");
    }
}

class DaZhong extends Car{
    @Override
    public void createCar() {
        System.out.println("造大众汽车");
    }
}

3、里氏替换原则

使用父类的地方,都可以替换成子类,程序不会产生任何错误和异常。

子类继承父类后,子类对父类方法进行重写时,需要注意:本来是要用父类中的方法,但是 子类重新修改了功能,可能会导致结果不正确。尽量不要重写父类的方法,可以新增扩展其他的功能。

package com.ffyc.javapro.ooptenet.tenet3;
public class CalculatorDemo{
    public static void main(String[] args) {
        System.out.println(new SuperCalculator().sum(5,5,5));
    }
}
//计算器
class Calculator {
    //加法
    public int add(int a,int b){
        return a+b;
    }
   //减法
    public int sub(int a,int b){
        return a-b;
    }
}
//超级计算器子类
class SuperCalculator extends Calculator{
    //重写了父类加法
    @Override
    public int add(int a, int b) {
        return a+b+5;
    }

    //求和方法 子类新增的功能
    public int sum(int a,int b,int c){
        //调用add(),但是子类重写了父类方法,此处调用的子类方法发生了变化
        int result = this.add(a,b);
        return result+c;
    }
}

4、依赖倒置

如果有多个同类型时,需要抽取抽象层(抽象类、接口)。上层定义为抽象或接口,底层实现抽象或接口,进行扩展功能。

//反例
public class WorkerDemo{
    public static void main(String[] args) {
        new Worker().getMessage(new DingDing());
        new Worker().getMessage(new WeChat());
    }
}

 class Worker {
    public void getMessage(DingDing ding){
        System.out.println(ding.sendMessage());
    }
    public void getMessage(WeChat weChat){
         System.out.println(weChat.sendMessage());
    }
}

class DingDing{
    public String sendMessage(){
         return "钉钉消息";
    }
}

class WeChat{
    public String sendMessage(){
        return "微信消息";
    }
}
//正例
public class WorkerDemo{
    public static void main(String[] args) {
        new Worker().getMessage(new WeChat());
    }
}

class Worker {
    public void getMessage(Message message){
        System.out.println(message.sendMessage());
    }
}

interface Message{
    public String sendMessage();
}

class WeChat implements Message{
    @Override
    public String sendMessage() {
        return "微信消息";
    }
}
class DingDing implements Message{
    @Override
    public String sendMessage() {
        return "钉钉消息";
    }
}

5、接口隔离

接口功能设计时,尽量减少一个接口中有过多的功能(方法),可以细分为多个接口。不要把所有的功能定义到同一个接口中,不然要实现接口中的所有方法。

6、迪米特原则

也叫最少了解原则,在一个类中,尽量不要直接使用与此类无关的类;只与最好的朋友交谈,不与默认人说话。

反例:

public class Demeter {
    public static void main(String[] args) {
        new SchoolManger().printAllEmployee(new CollegeManger());
    }
}
//学校员工类
class SchoolEmployee{
    private String id;
    public void setId(String id){
        this.id = id;
    }
    public String getId(){
        return id;
    }
}
//学院员工类
class CollegeEmployee{
    private String id;
    public void setId(String id){
        this.id = id;
    }
    public String getId(){
        return id;
    }
}

//学院员工管理管理类
class CollegeManger{
    //生成学员所有的员工
    public List<CollegeEmployee> getCollegeEmployee(){
        ArrayList<CollegeEmployee> collegeEmployeeArrayList = new ArrayList();
        for (int i = 0; i <10 ; i++) {
            CollegeEmployee collegeEmployee = new CollegeEmployee();
            collegeEmployee.setId("学院员工的id="+i); //添加学院员工
            collegeEmployeeArrayList.add(collegeEmployee);
        }
        return collegeEmployeeArrayList;
    }

}
//学校员工管理类
class SchoolManger {
    //生成学校的员工
    public List<SchoolEmployee> getSchoolEmployee() {
        ArrayList<SchoolEmployee> employeeArrayList = new ArrayList();
        for (int i = 0; i < 5; i++) {
            SchoolEmployee employee = new SchoolEmployee();
            employee.setId("学校的员工id=" + i);
            employeeArrayList.add(employee);
        }
        return employeeArrayList;
    }

    //输出学校员工和学院员工信息
    public void printAllEmployee(CollegeManger collegeManger) {
        //获取到学校员工
        List<SchoolEmployee> employeeArrayList = this.getSchoolEmployee();
        System.out.println("--------学校员工--------");
        for (SchoolEmployee employee1 : employeeArrayList) {
            System.out.println(employee1.getId());
        }

        System.out.println("--------学院员工--------");
        List<CollegeEmployee> collegeEmployees = collegeManger.getCollegeEmployee();
        //SchoolManger中出现CollegeEmployee,此类与SchoolManger并非直接朋友,不合理
        for (CollegeEmployee collegeEmployee : collegeEmployees) {
            System.out.println(collegeEmployee.getId());
        }
    }
}

正例:

public class Demeter {
    public static void main(String[] args) {
         new SchoolManger().printAllEmployee(new CollegeManger());
    }
}
//学校员工类
class SchoolEmployee{
    private String id;
    public void setId(String id){
        this.id = id;
    }
    public String getId(){
        return id;
    }
}
//学院员工类
class CollegeEmployee{
    private String id;
    public void setId(String id){
        this.id = id;
    }
    public String getId(){
        return id;
    }
}

//学院员工管理管理类
class CollegeManger{
    //生成学院所有的员工
    public List<CollegeEmployee> getCollegeEmployee(){
        ArrayList<CollegeEmployee> collegeEmployeeArrayList = new ArrayList();
        for (int i = 0; i <10 ; i++) {
            CollegeEmployee collegeEmployee = new CollegeEmployee();
            collegeEmployee.setId("学院员工的id="+i); //添加学院员工
            collegeEmployeeArrayList.add(collegeEmployee);
        }
        return collegeEmployeeArrayList;
    }

    public void printCollegeEmployee(){
        List<CollegeEmployee> collegeEmployee = getCollegeEmployee();
        for (CollegeEmployee employee : collegeEmployee) {
            System.out.println("学员员工id="+employee.getId());
        }
    }
}
//学校员工管理类
class SchoolManger {
    //生成学校的员工
    public List<SchoolEmployee> getSchoolEmployee() {
        ArrayList<SchoolEmployee> employeeArrayList = new ArrayList();
        for (int i = 0; i < 5; i++) {
            SchoolEmployee employee = new SchoolEmployee();
            employee.setId("学校的员工id=" + i);
            employeeArrayList.add(employee);
        }
        return employeeArrayList;
    }

    //输出学校员工和学院员工信息
    public void printAllEmployee(CollegeManger collegeManger) {
        //获取到学校员工
        List<SchoolEmployee> employeeArrayList = this.getSchoolEmployee();
        System.out.println("--------学校员工--------");
        for (SchoolEmployee employee1 : employeeArrayList) {
            System.out.println(employee1.getId());
        }

        //CollegeManger与SchoolManger是直接朋友,相互之间访问
        System.out.println("--------学院员工-----------");
                collegeManger.printCollegeEmployee();
    }
}

7、组合/聚合复用原则

如果想在一个类中达到复用别的类中的方法,优先使用关联/依赖,其次才考虑继承。

案例:现在假设有一个A类,里面有两个方法,B类想要复用这两个方法,请问有几种方案?

public class A {
    public void method01(){}
    public void method02(){}
}

class B{
    A a;//关联关系。A作为B类的成员变量,尽量避免使用继承
    public void setA(A a){
       this.a = a;
    }
    public void use(){
       a.method01();
       a.method02();
    }
}

class Test{
    public static void main(String[] args) {
         A a = new A();
         B b = new B();
         b.setA(a);
         b.use();
    }
}
public class A {
    public void method01(){}
    public void method02(){}
}

class B{
    public void use(A a){//将A作为参数使用,依赖关系
        a.method01();
        a.method02();
    }
}

class Test{
    public static void main(String[] args) {
         A a = new A();
         B b = new B();
         b.use(a);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/136607.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

由浅入深学习统计学 - 常用统计图形学习

学习笔记 第一章- 信息图形化 图形化&#xff08;可视化&#xff09; 在一堆数据中&#xff0c;自己发现了这些数据的规律&#xff0c;但是无法表述给其他人知道&#xff0c;图形化就是便于他人理解数据的规律的展示的手段。 或者说我们也可以从统计的数据图形中发现某些没有…

数据结构之带头双向循环链表

前言&#xff1a; 前面我们已经学习了顺序表和单链表&#xff0c;那么我们今天来学习数据结构中的另外一个线性表——带头双向循环链表。 带头双向循环链表&#xff1a; 头结点&#xff1a;带头也就是我们常说的“哨兵位”&#xff0c;头结点其中不存放任何的数据。哨兵位的存在…

【23种设计模式】依赖倒置原则

个人主页&#xff1a;金鳞踏雨 个人简介&#xff1a;大家好&#xff0c;我是金鳞&#xff0c;一个初出茅庐的Java小白 目前状况&#xff1a;22届普通本科毕业生&#xff0c;几经波折了&#xff0c;现在任职于一家国内大型知名日化公司&#xff0c;从事Java开发工作 我的博客&am…

Linux之gdb

gdb就是一个Linux的调试工具&#xff0c;类似与vs里面的调试 可执行程序也有格式&#xff0c;不是简单的二进制堆砌

【Unity之UI编程】玩法面板的实现

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;UI_…

【Linux】:静动态库

静动态库 一.静态库1.设计静态库2.生成静态库3.发布静态库4.使用静态库 二.动态库1.设计动态库2.生成和发布动态库3.使用 一.静态库 程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库。 静态库链接格式&#xff1a;libxxx.a(前缀是lib,后缀是…

CompareM-平均氨基酸一致性(AAI)计算

文章目录 Comparem简介比较基因组统计基因组使用模式其他 安装使用基于基因组计算氨基酸一致性基于基因组蛋白计算氨基酸一致性 结果转变成矩阵参考 Comparem简介 CompareM 是一个支持进行大规模基因组比较分析的软件工具包。它提供跨基因组&#xff08;如氨基酸一致性&#x…

git命令汇总

1.git是基于ssh的代码管理工具,所以在git使用之前需要配置好ssh ssh配置教程 2.先创建仓库 3. git init在目标的git目录下创建仓库 4.git add .(或者写文件名) 5.git commit -m "标记信息" 持久化 6.git remote add origin gitgit.acwing.com:yaoaolong/11_5.git初次…

如何判断一个角是否大于180度(2)

理论计算见上一篇&#xff1a; 如何判断一个角是否大于180度&#xff1f;_kv1830的博客-CSDN博客 此篇为代码实现 一。直接上代码&#xff1a; import cv2 as cv import numpy as np import mathdef get_vector(p_from, p_to):return p_to[0] - p_from[0], p_to[1] - p_from…

(头哥)多表查询与子查询

目录 第1关&#xff1a;查询每个学生的选修的课程信息 第2关&#xff1a;查询选修了“数据结构”课程的学生名单 第3关&#xff1a;查询“数据结构”课程的学生成绩单 第4关&#xff1a;查询每门课程的选课人数 第5关&#xff1a;查询没有选课的学生信息 第6关&#xff1a…

Doris:读取Doris数据的N种方法

目录 1.MySQL Client 2.JDBC 3. 查询计划 4.Spark Doris Connector 5.Flink Doris Connector 1.MySQL Client Doris 采用 MySQL 协议&#xff0c;高度兼容 MySQL 语法&#xff0c;支持标准 SQL&#xff0c;用户可以通过各类客户端工具来访问 Doris。登录到doris服务器后&a…

华为ensp:ospf动态路由

ip已配置好了 &#xff0c;现在进入路由器去宣告网段 R1 进入系统视图 ospf 1 area 1 network 192.168.1.0 0.0.0.255 network 1.1.1.0 0.0.0.255 R2 进入系统视图 ospf 1area 1 network 1.1.1.0 0.0.0.255 quit area 0 network 192.168.2.0 0.0.0.255 network 2.2…

上机4KNN实验4

目录 编程实现 kNN 算法。一、步骤二、实现代码三、总结知识1、切片2、iloc方法3、归一化4、MinMaxScale&#xff08;&#xff09;5、划分测试集、训练集6、KNN算法 .py 编程实现 kNN 算法。 1、读取excel表格存放的Iris数据集。该数据集有5列&#xff0c;其中前4列是条件属性…

[CISCN 2023 西南]do_you_like_read

打开题目&#xff0c;大概是一个购买书籍的网站&#xff0c;有登陆的功能 我们可以先分析下给的源码 在admin.php中会验证是否为admin用户 我们尝试爆破下密码&#xff0c;爆出来为admin123 登陆后发现存在文件上传漏洞 我们分析下源码 存在文件后缀检测&#xff0c;如果为p…

交换机工作原理

交换机工作原理 交换机功能&#xff1a;端口扩展&#xff08;默认同一网络&#xff09;&#xff0c;如果只是两台设备进行通信&#xff0c;可以直接连接这两台设备而不用交换机&#xff0c;但如果设备较多&#xff0c;设备没有那么多接口&#xff0c;那么这个时候就需要交换机…

三分钟学完Git版本控制常用指令

基本指令 git clone [url] 克隆远程仓库到本地 git clone https://gitee.com/mayun2023a/mprpc.git2.git checkout -b xxx 切换至新分支xxx&#xff08;相当于复制了remote的仓库到本地的xxx分支上) 3.修改或者添加本地代码&#xff08;部署在硬盘的源文件上&#xff09; 4.g…

Django配置文件,request,链接mysql方法,Orm简介

三板斧问题(views.py) HttpResponse # 返回的是字符串render # 渲染一个HTML静态文件&#xff0c;模板文件redirect # 重定向的 在视图文件中得视图函数必须要接收一个形参request&#xff0c;并且&#xff0c;视图函数也要有返回值&#xff…

着实不错的自适应大邻域搜索算法ALNS

文章目录 引言演进路线邻域搜索&#xff0c;NS变邻域搜素&#xff0c;VDNS大邻域搜索&#xff0c;LNS自适应大邻域搜索&#xff0c;ALNS 代码实现34个国内城市的TSP测试集XQF131 相关阅读 引言 之前介绍的差分进化算法和蚁群算法分别适用于求解连续优化问题和组合优化问题&…

【第五章】软件设计师 之 系统安全分析与设计

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 1、信息系统安全属性 2、对称加密与非对称加…

Redis五种数据类型及命令操作(二)

&#x1f388;个人公众号:&#x1f388; :✨✨✨ 可为编程✨ &#x1f35f;&#x1f35f; &#x1f511;个人信条:&#x1f511; 知足知不足 有为有不为 为与不为皆为可为&#x1f335; &#x1f349;本篇简介:&#x1f349; 本篇记录Redis五种数据类型及命令操作&#xff0c;如…