JAVASE进阶(设计模式、设计原则)(更新中...)

目录

一、注解

内置注解:JAVA中已经定义好的注解。

元注解:修饰注解的注解。

自定义注解。

二、克隆 

JAVA中对clone的实现?

浅克隆

深克隆

 那么该如何做到深克隆呢?

三、常用设计模式

        1、创建型模式

        单例模式

        工厂模式

        工厂方法模式 

        抽象工厂模式

        原型模式


一、注解

java中的注解也称标注,可以用来对类、方法、属性、参数、包等进行标注。然后让编译器或运行时其他类进行解析。完成某个功能注解也可以编译到字节码文件中。

内置注解:JAVA中已经定义好的注解。
@Override - 检查该方法是否是重写方法。如果发现其父类,或者是引用的接
口中并没有该方法时,会报编译错误。
@Deprecated - 标记过时方法。如果使用该方法,会报编译警告。
@SuppressWarnings - 指示编译器去忽略注解中声明的警告。
@FunctionalInterface 用于指示被修饰的接口是函数式接口。
元注解:修饰注解的注解。
@Retention - 标识这个注解怎么保存,是只在代码中,还是编入 class 文件中,
或者是在运行时可以通过反射访问。
@Documented - 标记这些注解是否包含在用户文档中。
@Target - 标记这个注解应该是哪种 Java 成员。
@Inherited - 标记这个注解是继承于哪个注解类(默认注解并没有继承于任何
子类)
@Repeatable - 标识某注解可以在同一个声明上使用多次。
自定义注解。

二、克隆 

克隆分为浅克隆、深克隆。

JAVA中对clone的实现?

①实现Cloneable接口

②重写clone方法(Object类中的方法)

浅克隆

克隆一个对象时,如果对象中有关联关系(has-a,把一个类当作另一个类的属性),只将关联对象的地址复制过来(只拿地址)

举例:

public class CloneDemo {
    public static void main(String[] args) throws CloneNotSupportedException {
        Student s1=new Student();
        Address address=new Address();
        address.setAddress("江苏");
        s1.setName("Mike");
        s1.setAge(20);
        s1.setAddress(address);

        Student s2=s1.clone();
        s2.setAge(21);
        s2.setName("Amy");
        address.setAddress("陕西");
        s2.setAddress(address);
        System.out.println(s1);
        System.out.println(s2);
    }
}
public class Student implements Cloneable{
    int age;
    String name;
    Address address;

    @Override
    protected Student clone() throws CloneNotSupportedException {
        return (Student) super.clone();
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", address=" + address.address +
                '}';
    }
}

public class Address {
    String address;

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

运行结果

这是一个浅克隆的例子, 主函数中定义了一个叫Mike的Student对象实例,Student类中有基本类型age和name,还有引用类型Address。我们在主函数中使用了Object类中的方法clone() (重写了该方法)

    @Override
    protected Student clone() throws CloneNotSupportedException {
        return (Student) super.clone();
    }

从运行结果发现基本数据类型修改不影响被克隆的对象,但是关联对象数据被修改,克隆的和被克隆的对象都被修改了。可以证明 浅克隆的定义:克隆一个对象时,如果对象中有关联关系(has-a,把一个类当作另一个类的属性),只将关联对象的地址复制过来(只拿地址)

所以浅克隆支持引用类型成员变量的复制 

并且我们发现,克隆的对象和被克隆的对象的地址不同,即使用clone()方法 会创建一个新对象,这里区别于JAVA中的引用

深克隆

克隆一个对象时,如果对象中有关联关系,将关联对象一同克隆(创建一个新的关联对象)

 那么该如何做到深克隆呢?

1、连同关联对象一同克隆,逐级克隆(层级过多会比较麻烦)

public class CloneDemo {
    public static void main(String[] args) throws CloneNotSupportedException {
        Student s1=new Student();
        Address address=new Address();
        address.setAddress("江苏");
        s1.setName("Mike");
        s1.setAge(20);
        s1.setAddress(address);

        Student s2=s1.clone();
        s2.setAge(21);
        s2.setName("Amy");
        address.setAddress("陕西");
        System.out.println(s1);//Mike 20 陕西
        System.out.println(s2);//Amy 21 江苏
    }
}
public class Student implements Cloneable{
    int age;
    String name;
    Address address;

    @Override
    protected Student clone() throws CloneNotSupportedException {
        Student s=(Student) super.clone();
        Address address=(Address)s.getAddress().clone();
        s.setAddress(address);
        return s;
    }
}
public class Address implements Cloneable{
    String address;

    @Override
    protected Address clone() throws CloneNotSupportedException {
        return (Address) super.clone();
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

 在Student类中再使用clone()方法克隆Address对象,并且在Address类中重写clone()方法。

运行结果

通过结果发现,改变了关联对象地址,克隆对象的地址并未改变,说明深克隆不支持引用类型成员变量的复制。 

2、序列化(对象的输入输出流)

三、常用设计模式

        1、创建型模式

         用于描述“怎样创建对象”,它的主要特点是“将对象的创建与使 用分离”。提供了单例、原型、工厂方法、抽象工厂、建造者 5 种创建型模式。

        单例模式

        在有些系统中,为了节省内存资源、保证数据内容的一致性,对某些类要求 只能创建一个实例,这就是所谓的单例模式. 例如,Windows 中只能打开一个 任务管理器,这样可以避免因打开多个任务管理器窗口而造成内存资源的浪费, 或出现各个窗口显示内容的不一致等错误。单例模式有 3 个特点: 1. 单例类只有一个实例对象; 2. 该单例对象必须由单例类自行创建; 3. 单例类对外提供一个访问该单例的全局访问点;

        工厂模式

1、简单工厂:有一个工厂类负责生产某一类产品,同一类产品具备同一个抽象父类(抽象类/接口)。将创建对象与使用对象分离(Spring框架的设计思想)。简单工厂违背了开闭原则,添加一个产品就需要修改代码。子类过多,会导致工厂类庞大

以手机工厂为例:

手机接口:

public interface Phone {
    public  void run();
}

手机工厂接口:

public interface PhoneFactory {
    void createPhone();
}

有两种品牌的手机:HUAWEI和IPhone

手机工厂,重写创建手机方法

public class PhoneFactory {
    static Phone createPhone(String name) {
        if (name.equals("HUAWEI")) {
            return (Phone) new HUAWEI();
        }else if(name.equals("IPhone")){
            return (Phone) new IPhone();
        }else {
            return null;
        }
    }
}

华为手机运行

public class HUAWEI implements Phone{

    @Override
    public void run() {
        System.out.println("使用华为手机");
    }
}

iPhone手机运行

public class IPhone implements Phone{

    @Override
    public void run() {
        System.out.println("使用苹果手机");
    }
}

主函数

public class Solution {
    public static void main(String[] args) {
        PhoneFactory huaweiFactory=new HUAWEIFactory();
        Phone huaweiPhone=new HUAWEI();
        huaweiPhone.run();

        PhoneFactory iphoneFactory=new IPhoneFactory();
        Phone iphonePhone=new IPhone();
        iphonePhone.run();
    }
}

运行结果:

        工厂方法模式 

对工厂进行抽象,一个抽象的产品对应一个抽象的工厂。一个具体的产品对应一个具体的工厂,一个具体的工厂负责生产一个具体的产品,需要扩展新产品时,只需要添加新的具体的产品类,和新的生产该产品的工厂类即可。这样就不需要修改原来的工厂,符合开闭原则。

手机接口:

public interface Phone {
    public  void run();
}

手机工厂接口:

public interface PhoneFactory {
    void createPhone();
}

有两种品牌的手机:HUAWEI和IPhone

HUAWEI手机工厂

public class HUAWEIFactory implements PhoneFactory{
    @Override
    public void createPhone() {
        new HUAWEI();
    }
}

iPhone手机工厂

public class IPhoneFactory implements PhoneFactory{
    @Override
    public void createPhone() {
        new IPhone();
    }
}

华为手机运行

public class HUAWEI implements Phone{

    @Override
    public void run() {
        System.out.println("使用华为手机");
    }
}

iPhone手机运行

public class IPhone implements Phone{

    @Override
    public void run() {
        System.out.println("使用苹果手机");
    }
}

主函数

public class Solution {
    public static void main(String[] args) {
        PhoneFactory huaweiFactory=new HUAWEIFactory();
        Phone huaweiPhone=new HUAWEI();
        huaweiPhone.run();

        PhoneFactory iphoneFactory=new IPhoneFactory();
        Phone iphonePhone=new IPhone();
        iphonePhone.run();
    }
}

运行结果:

        抽象工厂模式

抽象工厂时生产一系列产品(某公司的产品华为手机,华为汽车),在抽象工厂中定义生产不同的产品,具体工厂负责生产一个公司的一系列产品

 定义一个抽象工厂

public interface AbstractFactory {
    Car getCar();
    Phone getPhone();
}

定义 汽车接口,手机接口

public interface Phone {
    void call();
}

public interface Car {
    void run();
}

定义产品工厂

public class RedmiFactory implements AbstractFactory{
    @Override
    public Car getCar() {
       return new RedmiCar();
    }

    @Override
    public Phone getPhone() {
        return new RedmiPhone();
    }
}

产品信息

public class RedmiPhone implements Phone{
    @Override
    public void call() {
        System.out.println("红米手机,年轻人的选择");
    }
}
public class RedmiCar implements Car{

    @Override
    public void run() {
        System.out.println("米家汽车,安心可靠");
    }
}

 主函数

public class Solution {
    public static void main(String[] args) {
        AbstractFactory redmiFactory=new RedmiFactory();
        Car redmiCar=redmiFactory.getCar();
        Phone redmiPhone= redmiFactory.getPhone();
        redmiCar.run();
        redmiPhone.call();
    }
}

运行结果

        原型模式

原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能(new一个对象非常昂贵)。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式之一。

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

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

相关文章

从零学Java - Stream API

Java - Stream API 文章目录 Java - Stream API什么是流(Stream)?Stream 的特点Stream使用步骤1 创建 Stream流2 中间操作3 终止操作 什么是流(Stream)? 流(Stream)与集合类似,但集合中保存的是数据,而Stream中保存对集合或数组…

微信怎么设置自动回复?教程来咯!

自动回复信息 你有没有为了回复微信消息,中断工作进度,耽误了大量时间?或者错过了潜在客户?现在,我们的微信管理系统,可以帮助你在第一时间,实时回复用户消息。 01 # 通过好友自动打招呼# 我们…

技术浪潮中的职业变革:程序员面临的裁员挑战与应对策略

目录 前言 冲破时空壁垒:探索技术变革的酷时代! 逆境成长:一个互联网人战胜失业困境的故事 裁员的双面影响:挑战与机遇 应对裁员潮危机:程序员的超级英雄之路 前言 惊人的新闻传来,一对来自中国的工程师…

【Linux与windows的文件互相传输】

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 关于 rzsz 注意事项 查看软件包 使用命令 下载到本地(使用sz的命令) 本地文件上传到Linux中(使用rz命令) 方法一…

Jumpserver中安装httpx

查看已安装的包 pip freeze # python -V # Python 2.7.5安装anyio 刚开始直接pip install httpx,未设置版本号,因已有idna2.7,所以出现版本不兼容的现象 anyio 3.0.0 requires idna>2.8, but you have idna 2.7 which is incompatible.…

【python】python实现代码雨【附源码】

欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 一、效果图: 二、准备工作 (1)、导入必要的模块: 代码首先导入了需要使用的模块:requests、lxml和csv。 import requests from lxml import etree import csv 如果出现模…

惬意上手Python —— os模块

首先,这部分很简单,不需要有太多的操作,只需要用的时候你知道该用这个模块下的哪个函数。例如,你想知道当前路径,就该知道用 curdir 这个函数。 在Python中,os模块是一个与操作系统交互的标准库模块&…

前端面试题-(BFC,前端尺寸单位,网站页面常见的优化手段)

前端面试题-BFC,前端尺寸单位,网站页面常见的优化手段 BFC前端尺寸单位网站页面常见的优化手段 BFC BFC(block formartting context)块格式化上下文。是通过独立渲染的区域,它拥有自己的渲染规则,可以决定…

【Linux】-对于信号章节补充的知识点,以及多线程知识的汇总

💖作者:小树苗渴望变成参天大树🎈 🎉作者宣言:认真写好每一篇博客💤 🎊作者gitee:gitee✨ 💞作者专栏:C语言,数据结构初阶,Linux,C 动态规划算法🎄 如 果 你 …

pytest+allure 生成中文报告

背景 已安装pytestallure,生成的报告是英文 allure生成中文报告 参考:allure report 报告中文化及其它优化 方法1:直接在报告中切换中文 方法2:依赖系统中文语言 创建一个setting.js 文件在index.html 同级目录 // 尝试从 l…

Python - 【Socket】消息粘包处理demo(一)

一. 前言 在网络编程中,粘包是指TCP协议在传输过程中,多条数据被合并成一条数据发送或者一条数据被拆分成多个数据发送的现象。 二. 粘包问题的常规处理方法: 使用固定长度的包头 可以在发送数据前先发送一个固定长度的包头,包…

赠书活动~

关注公众号获得,发送抽奖

hcip---ppp协议

一:网络类型----根据二层数据链路层使用协议的不同,进行的划分 MA--多点接入网络 BMA--广播型多点接入网络 NBMA--非广播型多点接入网络 P2P--点到点网络:当网络中只能两台设备存在,那么这样的网络不需要MAC也能进行通信 二层协议…

用Axure RP 9制作滑块

制作流程 1.打开界面 放置一个水平线 修改长为400 线段为5 2.放入圆 如图 3.修改圆的长和宽 如图 4.将圆变成动态面板 5.设置交互事件 如图 6.增加交互事件 7.增加 8.修改成跟随水平

系统架构演变

1.1系统架构的演变 2008年以后,国内互联网行业飞速发展,我们对软件系统的需求已经不再是过去”能用就行”这种很low的档次了,像抢红包、双十一这样的活动不断逼迫我们去突破软件系统的性能上限,传统的IT企业”能用就行”的开发思…

查看并解析当前jdk的垃圾收集器

概述:复习的时候,学看一下。 命令: -XX:PrintCommandLineFlags 打开idea,配置jvm 把上面命令输入jvm options中即可。 举例代码 这个代码的解析,我上篇文章有写,这个跟本文没有任何关系: …

Elasticsearch 常用信息

简述 本文针对 Elasticsearch(简称ES)集群6.x版本出现故障时,可通过提供的命令进行排查。 1、集群健康状态 集群健康状态状态说明red不是所有的主要分片都可用。表示该集群中存在不可用的主分片。可以理解为某个或者某几个索引存在主分片丢失…

C#,入门教程(31)——预处理指令的基础知识与使用方法

上一篇: C#,入门教程(30)——扎好程序的笼子,错误处理 try catchhttps://blog.csdn.net/beijinghorn/article/details/124182386 Visual Studio、C#编译器以及C#语法所支持的预处理指令,绝对是天才设计。 编译程序的时候会发现&am…

AI搜索引擎Perplexity来了,谷歌等老牌搜索引擎或许会有新的威胁?

Perplexity AI 是一家 AI 搜索初创公司,它通过结合内容索引技术和大型语言模型的推理能力,提供更便捷和高效的搜索体验。另外,最近很火的小兔子Rabbit R1硬件AI设备中的搜索功能正是这家公司的杰作。在短短一年半的时间里,一个企业…

Qt6入门教程 10:菜单栏、工具栏和状态栏

目录 一.菜单栏 1.Qt Designer 1.1添加菜单和菜单项 1.2添加二级菜单 1.3给菜单和菜单项添加图标 1.4给菜单项添加功能 2.纯手写 二.工具栏 1.Qt Designer 1.1添加工具栏按钮 1.2工具栏的几个重要属性 2.纯手写 三.状态栏 1.Qt Designer 2.纯手写 用Qt Creator新…