网站续费查询,建设网站项目简历,推荐专业的网站建设公司,普通电脑怎么建设网站文章目录 注解内置注解元注解 对象克隆为什么要克隆#xff1f;如何克隆浅克隆深克隆 Java设计模式什么是设计模式#xff1f;为什么要学习设计模式#xff1f; 建模语言类接口类之间的关系依赖关系关联关系聚合关系组合关系继承关系实现关系 面向对象设计原则单一职责开闭原… 文章目录 注解内置注解元注解 对象克隆为什么要克隆如何克隆浅克隆深克隆 Java设计模式什么是设计模式为什么要学习设计模式 建模语言类接口类之间的关系依赖关系关联关系聚合关系组合关系继承关系实现关系 面向对象设计原则单一职责开闭原则里氏替换原则依赖倒置接口隔离迪米特原则组合/聚合服用原则原则总结设计原则的核心思想 23种设计模式常用的设计模式单例模式饿汉式单例懒汉式单例 Runtime类 注解
注解也叫标注用于包、类、变量、方法、参数上。可以通过反射获取标注。可以在编译期间使用也可以被编译到字节码文件中运行时生效。
内置注解
内置注解Java语言已经定义好的注解。
Overread用于方法重写。
Deprecated标记过时方法。
SuppressWarnings指示编译器去忽略注解中声明的警告。
FunctionalInterface用于指标被修饰的接口是函数式接口。
元注解
元注解修饰注解的注解。
Target用于描述注解作用于那些元素上。
CONSTRUCTOR//用于描述构造器
FIELD//用于描述域
LOCAL_VARIABLE//用于描述局部变量
METHOD//用于描述方法
PACKAGE//用于描述包
PARAMETER//用于描述参数
TYPE//用于描述类、接口(包括注解类型) 或enum声明Retention表示注解什么时候生效。
SOURCE//在源文件中有效即源文件保留
CLASS//在class文件中有效即class保留
RUNTIME//在运行时有效即运行时保留对象克隆
克隆在一个现有的对象基础上克隆一个新的对象。
为什么要克隆
通过new出来的对象所有属性都是空值或者默认值希望将原来对象的属性也一并赋值给一个新的对象。
//一下情况并不是克隆,只是将对象地址赋值给了另一个对象.
Student stu1 new Student();
Student stu2 stu1;如何克隆
类实现Cloneable接口重写Object类中的clone方法。通过序列化来实现。
java语言中数据类型分为基本数据类型和引用数据类型基本数据类型的值可以直接进行复制但是引用数据类型只能复制引用地址。所以浅克隆和深克隆的区别就在于是否支持引用类型的成员变量的复制。
浅克隆
不支持对象中的引用类型复制值仅仅复制地址。
简单来说就是当对象被克隆时只复制它本身和其他基本数据类型的成员变量而引用类型的对象并没有复制。
深克隆
支持对象中的引用类型成员变量复制值引用类型成员变量也会克隆一个新的对象。
简单来说就是除了对象本身被复制外对象包含的所有成员变量也将复制。
Java设计模式
设计模式本来是在建筑上使用的后来运用于程序设计。
什么是设计模式
设计模式是指一套被反复使用代码设计经验的总结。针对一些问题的解决方式经过很长时间的修改打磨最终成为一种固定的模式。
为什么要学习设计模式
在面向对象的基础上继承、封装、多态更好的理解和运用。
使用设计模式的优点
可以提高程序员的思维、编程、设计能力
使程序更加标准化提高软件开发效率
使得代码的可重用性高可读性强灵活性好可维护性强
更好的理解源代码。
建模语言
统一建模语言Unified Modeling LanguageUML是一种用于软件系统分析和设计的语言工具用于帮助开发人员进行思考和记录思路的结果。
UML图通过不同的图形和符号描述软件模型以及各个元素之间的联系。
类图是显示了模型的静态结构特别是模型中存在的类、类的内部结构以及他们与其它类之间的关系等。类图是面向对象建模的主要组成部分。
类图是一种静态的结构图描述了系统的类的集合类的属性和类之间的关系可以简化人们对系统的理解类图是系统分析与设计的产物。
类
类是指具有相同属性、方法和关系的对象的抽象它封装了数据的行为是面向对象程序设计的基础具有封装、继承和多态三种特性。
在UML中类的UML —nolong 表示不可见参数no的数据类型为long
displayvoid表示方法display为public且返回值为void
protected#
接口
接口是一种特殊的类它具有类的结构但是不能实例化只可以被子类实现。它包含抽象操作但是不包含属性。它描述了类或组件对外可见的动作。
在UML中接口使用一个带有名称的圆圈表示。 类之间的关系
在系统中类并不是孤立存在的类与类之间存在一定关系的。根据类之间的耦合度从弱到强依次为依赖关系、关联关系、聚合关系、组合关系、泛化关系和实现关系。
依赖关系
依赖关系是一种临时关系。代码中某个类的方法通过局部变量、方法的参数或者对静态方法的调用来访问另一个类被依赖类中的某些方法来完成某些功能。
在UML类图中依赖关系使用带箭头的虚线表示从使用类指向被依赖类。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lLETOFmh-1692757184340)( )]
关联关系
关联关系是对象之间的一种引用关系用于表示一类对象与另一类对象之间的联系如老师与学生等。关联关系是类与类之间最常用的一种关系分为关联关系聚合关系和组合关系。
关联关系一般分为单向关联、双向关联、自关联。
单向关联 在 UML 类图中单向关联用一个带箭头的实线表示。上图表示每个顾客都有一个地址这通过让 Customer 类持有一个类型为 Address 的成员变量类实现。
双向关联 从上图中我们很容易看出所谓的双向关联就是双方各自持有对方类型的成员变量。
在 UML 类图中双向关联用一个不带箭头的直线表示。
自关联 自关联在 UML 类图中用一个带有箭头且指向自身的线表示。上图的意思就是Node 类包含类型为 Node 的成员变量也就是“自己包含自己”。
聚合关系
聚合关系是关联关系的一种是整体与部分之间的关系。
聚合关系也是通过成员对象来实现的其中成员对象是整体对象的一部分但是成员对象可以脱离整体对象而独立存在。例如学校与老师的关系学校包含老师但如果学校停办了老师依然存在。 在 UML 类图中聚合关系可以用带空心菱形的实线来表示菱形指向整体。
组合关系
组合表示类之间的整体与部分的关系但它是一种更强烈的聚合关系。
在组合关系中整体对象可以控制部分对象的生命周期一旦整体对象不存在部分对象也将不存在部分对象不能脱离整体对象而存在。例如头和嘴的关系没有了头嘴也就不存在了。 在 UML 类图中组合关系用带实心菱形的实线来表示菱形指向整体。
继承关系
继承关系是对象之间耦合度最大的一种关系表示一般与特殊的关系是父类与子类之间的关系是一种继承关系。 在 UML 类图中继承关系用带空心三角箭头的实线来表示箭头从子类指向父类。在代码实现时使用面向对象的继承机制来实现继承关系。例如上图 Student 类和 Teacher 类都是 Person 类的子类。
实现关系
实现关系是接口与实现类之间的关系。在这种关系中类实现了接口类中的操作实现了接口中所声明的所有的抽象操作。 在 UML 类图中实现关系使用带空心三角箭头的虚线来表示箭头从实现类指向接口。例如上图汽车和船实现了交通工具。
面向对象设计原则
如何同时提高系统的可维护性和可服用性。就需要遵从面向对象语言设计原则可以在进行设计方案时减少设计错误提高软件的实际水平。
单一职责
单一职责可以理解为一个类只负责一个功能领域中的相应职责。
优点低耦合、高内聚。
开闭原则
开闭原则扩展开放修改关闭。
系统的需求是一直在变化的因此在设计时需要考虑怎样设计才能在需求改变时系统依旧可以稳定。
需要系统进行抽象化设计抽象化是开闭原则的关键。在进行软件设计时提前将一些可能会改变的类设计为抽象类来隔离变化。在发生变化时无需对抽象类进行改动只需要添加具体类来实现业务功能即可。在不修改自己原有的代码的基础上扩展功能。
/*开闭原则案例*/
public class CarDemo {public static void main(String[] args) {new CarFactory().createCar(1);new CarFactory().createCar(2);new CarFactory().createCar(3);new CarFactory().createCar(4);new CarFactory().createCar(5);}}/*汽车工程类,专门负责造汽车*/
class CarFactory{/*违反了开闭原则,后期如果添加新的汽车类,则需要修改代码*/public void createCar(int type){if(type1){System.out.println(造宝马汽车new Car(宝马汽车));}else if(type2){System.out.println(造奥迪汽车new Car(奥迪汽车));}else{System.out.println(造大众汽车new Car(大众汽车));}}}class Car{String name;public Car(String name) {this.name name;}
}
class CarDemo{public static void main(String[] args) {new CarFactory().carfactory(new BMW());new CarFactory().carfactory(new Aodi());new CarFactory().carfactory(new DaZhong());}}class CarFactory{void carfactory(Car car){car.createCar();}
}//扩展业务时只需要继承Car类无需修改原代码
abstract class Car{public abstract void createCar();
}class BMW extends Car{Overridepublic void createCar() {System.out.println(造宝马汽车);}
}class Aodi extends Car{Overridepublic void createCar() {System.out.println(造奥迪汽车);}
}class DaZhong extends Car{Overridepublic void createCar() {System.out.println(造大众汽车);}
}class BC extends Car{Overridepublic void createCar() {System.out.println(造奔驰汽车);}
}优点适应性强、灵活、稳定、可扩展性强、可复用。
里氏替换原则
回顾继承
优势提高了代码的复用性提高了代码的扩展性。
弊端继承是侵入式只要继承就必须拥有父类的属性和方法继承机制很大的增加了耦合性(父类被子类继承,父类功能修改会影响子类)。
里氏替换原则继承必须确保父类所拥有的性质子类中必然成立。
里氏替换原则的定义通俗的讲就是子类继承父类时除添加新的方法完成新增功能外尽量不要重写父类的方法。
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 ab;}//减法public int sub(int a,int b){return a-b;}
}
/*超级计算器子类
*/
class SuperCalculator extends Calculator{//重写了父类加法Overridepublic int add(int a, int b) {return ab5;}//求和方法 子类新增的功能public int sum(int a,int b,int c){//调用add(),但是子类重写了父类方法,此处调用的子类方法发生了变化这里相当于调用了重写的add方法int result add(a,b);//重写add后结果为20不重写结果为15return resultc;}
}里氏替换原则的作用功能正确性得到保障实现开闭原则的重要方式之一降低了需求变更时引入的风险。
依赖倒置
上层模块不应该依赖底层模块它们都应该依赖于抽象
简单讲就是要求对抽象进行编程不要对实现进行编程这样就降低了客户与实现模块间的耦合。就是针对抽象层编程面向接口编程。
接口隔离
使用多个接口而不使用单一的总接口不强迫新功能实现不需要的方法。
迪米特原则
一个对象应该对其他对象有最少的了解
就是只对直接朋友进行交流
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 ListCollegeEmployee getCollegeEmployee(){ArrayListCollegeEmployee collegeEmployeeArrayList new ArrayListCollegeEmployee();for (int i 0; i 10 ; i) {CollegeEmployee collegeEmployee new CollegeEmployee();collegeEmployee.setId(学院员工的idi); //添加学院员工collegeEmployeeArrayList.add(collegeEmployee);}return collegeEmployeeArrayList;}}
//学校员工管理类
class SchoolManger {//生成学校的员工public ListSchoolEmployee getSchoolEmployee() {ArrayListSchoolEmployee employeeArrayList new ArrayListSchoolEmployee();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) {//获取到学校员工ListSchoolEmployee employeeArrayList this.getSchoolEmployee();System.out.println(--------学校员工--------);for (SchoolEmployee employee1 : employeeArrayList) {System.out.println(employee1.getId());}System.out.println(--------学院员工--------);ListCollegeEmployee collegeEmployees collegeManger.getCollegeEmployee();//此处学校管理类中出现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 ListCollegeEmployee getCollegeEmployee(){ArrayListCollegeEmployee collegeEmployeeArrayList new ArrayListCollegeEmployee();for (int i 0; i 10 ; i) {CollegeEmployee collegeEmployee new CollegeEmployee();collegeEmployee.setId(学院员工的idi); //添加学院员工collegeEmployeeArrayList.add(collegeEmployee);}return collegeEmployeeArrayList;}public void printCollegeEmployee(){ListCollegeEmployee collegeEmployee getCollegeEmployee();for (CollegeEmployee employee : collegeEmployee) {System.out.println(学员员工idemployee.getId());}}}
//学校员工管理类
class SchoolManger {//生成学校的员工public ListSchoolEmployee getSchoolEmployee() {ArrayListSchoolEmployee employeeArrayList new ArrayListSchoolEmployee();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) {//获取到学校员工ListSchoolEmployee employeeArrayList this.getSchoolEmployee();System.out.println(--------学校员工--------);for (SchoolEmployee employee1 : employeeArrayList) {System.out.println(employee1.getId());}//CollegeManger与SchoolManger是直接朋友,相互之间访问System.out.println(--------学员员工-----------);collegeManger.printCollegeEmployee();}
}组合/聚合服用原则
优先使用组合使系统更灵话其次才考虑继承达到复用的目的。
案例:现在假设有一个 A 类里面有两个方法有一个类 B想要复用这两个方法请问有几种方案?
方案一让B继承A
方案二B中引用A
方案三方法传参
原则总结
开闭原则要求对扩展开放对修改关闭
里氏替换原则不要破坏继承体系
依赖倒置原则要求面向接口编程
单一职责原则实现类职责要单一
接口隔离原则在设计接口的时候要精简单一
迪米特法则只与直接的朋友的通信
合成复用原则尽量使用聚合和组合的方式而不是使用继承
设计原则的核心思想
找出应用中可能需要变化之处独立出来不要和不需要变化的代码混在一起
针对接口编程而坏是针对实现编程
为了交互对象的松耦合设计而努力
遵循设计原则就是为了让程序高内聚低耦合
23种设计模式
https://www.runoob.com/design-pattern/design-pattern-tutorial.html
单例Singleton模式某个类只能生成一个实例该类提供了一个全局访问点供外部获取该实例其拓展是有限多例模式。原型Prototype模式将一个对象作为原型通过对其进行复制而克隆出多个和原型类似的新实例。工厂方法Factory Method模式定义一个用于创建产品的接口由子类决定生产什么产品。抽象工厂AbstractFactory模式提供一个创建产品族的接口其每个子类可以生产一系列相关的产品。建造者Builder模式将一个复杂对象分解成多个相对简单的部分然后根据不同需要分别创建它们最后构建成该复杂对象。代理Proxy模式为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象从而限制、增强或修改该对象的一些特性。适配器Adapter模式将一个类的接口转换成客户希望的另外一个接口使得原本由于接口不兼容而不能一起工作的那些类能一起工作。桥接Bridge模式将抽象与实现分离使它们可以独立变化。它是用组合关系代替继承关系来实现从而降低了抽象和实现这两个可变维度的耦合度。装饰Decorator模式动态的给对象增加一些职责即增加其额外的功能。外观Facade模式为多个复杂的子系统提供一个一致的接口使这些子系统更加容易被访问。享元Flyweight模式运用共享技术来有效地支持大量细粒度对象的复 用。组合Composite模式将对象组合成树状层次结构使用户对单个对象和组合对象具有一致的访问性。模板方法TemplateMethod模式定义一个操作中的算法骨架而将算法的一些步骤延迟到子类中使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。策略Strategy模式定义了一系列算法并将每个算法封装起来使它们可以相互替换且算法的改变不会影响使用算法的客户。命令Command模式将一个请求封装为一个对象使发出请求的责任和执行请求的责任分割开。职责链Chain of Responsibility模式把请求从链中的一个对象传到下一个对象直到请求被响应为止。通过这种方式去除对象之间的耦合。状态State模式允许一个对象在其内部状态发生改变时改变其行为能 力。观察者Observer模式多个对象间存在一对多关系当一个对象发生改变时把这种改变通知给其他多个对象从而影响其他对象的行为。中介者Mediator模式定义一个中介对象来简化原有对象之间的交互关系降低系统中对象间的耦合度使原有对象之间不必相互了解。迭代器Iterator模式提供一种方法来顺序访问聚合对象中的一系列数 据而不暴露聚合对象的内部表示。访问者Visitor模式在不改变集合元素的前提下为一个集合中的每个元素提供多种访问方式即每个元素有多个访问者对象访问。备忘录Memento模式在不破坏封装性的前提下获取并保存一个对象的内部状态以便以后恢复它。解释器Interpreter模式提供如何定义语言的文法以及对语言句子的解释方法即解释器。
常用的设计模式
单例模式
有些系统或者项目中为了节省资源、保证数据内容的一致性对某些类要求只能创建一个对象实例。如Windows中的只能打开一个任务管理器这样可以避免因为打开多个任务管理器窗口而造成内存资源浪费或者出现各个窗口显示的内容不一致等错误。
特点
只能有一个实例对象
单例对象必须由单例类自行创建关联关系中的自关联
单例类需要对外提供一个访问单例的全局访问点
单例模式实现形式有两种饿汉式、懒汉式。
饿汉式单例
在类被加载时创建对象不存在线程安全问题。
public class Window {//创建静态对象随着类的加载一起加载private static Window window new Window();private Window(){}//构造方法私有化防止外部直接构造//提供给外部获取实例对象的方法public static Window getWindow() {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}return window;}
}public class Test {public static void main(String[] args) {for (int i 0; i 10; i) {new Thread(()-{System.out.println(Window.getWindow());}).start();}}
}
/*
com.single.demo1.Window6bfcab86
com.single.demo1.Window6bfcab86
com.single.demo1.Window6bfcab86
com.single.demo1.Window6bfcab86
com.single.demo1.Window6bfcab86
com.single.demo1.Window6bfcab86
com.single.demo1.Window6bfcab86
com.single.demo1.Window6bfcab86
com.single.demo1.Window6bfcab86
com.single.demo1.Window6bfcab86
*/
//由结果可以看出创建的十个对象是同一个对象懒汉式单例
在类加载的时候不创建对象在使用的时候创建。这时生成的对象需要我们自己进行控制存在线程安全问题。
public class Window {private static Window windownull;private Window(){}
/*懒汉式单例会出现线程安全问题:在多线程访问时,可能会有多个线程同时进行到if,就会创建出多个对象*/public static Window getWindow(){if(windownull){window new Window();}return window;}
}//解决方法1.给方法加锁, 可以解决,但是效率低,一次只能有一个线程进入获取public static synchronized Window getWindow() {if (window null) {window new Window();}return window;}//解决方法2.给代码块加锁,双重检索synchronized
public static Window getWindow(){if(windownull){synchronized(Window.class){if(window null){window new Window3();}}}return window;}经过上面两次改进任然存在问题就是指令重排问题new一个对象的时候一般步骤为申请空间——调用构造方法——将对象地址赋值给引用变量。
问题在一个线程先将半成品对象地址赋值给引用变量时暂停了另一线程来了引用变量不为空指向半成品对象。
解决方法在解决办法2的基础上加volatile
private static volatile Window windownull;Runtime类
Jdk 中的源码 Runtime 类就是一个单例类利用 Runtime 类可以启动新的进程或进行相关运行时环境的操作。比如取得内存空间以及释放垃圾空间。