JAVA设计模式
JAVA设计模式共有23中,其中:
(1)创建型模式(五种):工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式;
(2)结构型模式(七种):适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
(3)行为型模式(十一种):策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
创建型模式,顾名思义,是创建实例对象时使用的设计模式。
1 单例设计模式(Singleton)
单:唯一;
例:实例;
即,某个类在整个系统中只能有一个实例对象被获取和使用的代码模式,比如说我们电脑上的进程管理器,双击图标打开,再次双击图标依然弹出第一次双击出来的对话框,类似应用还有回收站/打印机,JVM运行环境Runtime类等。
常见场景:Windows 任务管理器;
Windwos 回收站;
项目中,读取配置文件的类,一般也只有一个对象,没有必要每次都去 new对象读取;
网站的计数器一般也会采取单例模式,可以保证同步;
数据库连接池的设计一般也是单例模式;
在Spring中,每个Bean就是默认单例的。
要点:1.某个类只能有一个实例;(构造器私有化)
2.他必须自行创建该实例;(含有一个该类的静态变量去保存这个唯一的实例)
3.他必须自行向系统提供整个实例。(对外提供获取该实例对象的方式:1.直接暴露;2.用静态变量的get方法获取)
拓展:
JAVA的成员变量有两种:
一种是被static关键字修饰的变量,叫类变量或者静态变量。
另一种没有static修饰,为成员变量
类的静态变量在内存中只有一个,Java虚拟机在加载类的过程中为静态变量分配内存,静态变量位于方法区,被类的所有实例所共享。静态变量可以通过类名去访问,而不要new一个对象去访问,它的生命周期取决于类的生命周期;
而实例变量取决于类的实例,也就是对象。每创建一个实例,Java虚拟机就会为变量分配一次内存,实例变量位于堆中,其生命周期取决于实例的生命周期。
java中引用都在栈里面,对象都在堆里,成员方法,比如int a =1,属于基本数据类型,放在栈中;而引用数据类型(包装类)这些都是引用在栈里,对象在堆里。
JAVA中初始化的顺序:
1.加载类;
2.静态变量初始化;(方法区)
3.静态块;【其只能调度静态的,不能调度非静态的】
4.成员变量;(堆)
5.构造方法;
构造方法:一般是用于初始化实例时使用的方法,与普通方法的区别在于,普通方法需要新建一个对象,去调用,而构造方法是对象生来就有的,不需要调用。
构造方法的几点特殊性:
1.构造方法的名字必须和定义它的类名称完全相同,没有返回类型,连void也没有;
2.类中必定有构造方法,不写系统默认赠送一个无参的构造方法。如果自己写了构造方法,系统便不在赠送;
接口不允许被实例化,因此接口中没有构造方法;
3.不能被static,final,synchronized,abstrctic和native修饰;
4.构造方法在初始化对象时自动执行,一般不能被显式的直接调用。当同一个类存在多个构造方法是,Java编译系统会自动按照初始化时最后面括号的参数个数以及参数类型来自动一一对应,完成构造函数的调用。
5.构造方法可以被重载,没有参数的构造方法称为默认构造方法,与普通方法一样,构造方法也是方法,可以将其设计为进行各种初始化活动,初始化对象的属性。
饿汉式
饿汉式,直接创建对象,不存在线程安全问题
/**
* 饿汉式:直接创建对象,不管你需不需要
*/
public class Singleton1 {
//(2)自行创建对象,并用静态变量保存
//(3)向外提供这个实例,因此用public修饰,
// (4)为了强化这个实例不能被修改,用final在此修饰--是一个单例
public final static Singleton1 INSTANCE = new Singleton1();
//(1)构造器私有化,不能让外部去实现这个实例
private Singleton1(){
}
}
/**
* 枚举类型:表示该类型的对象是有限的几个
* 我们可以限定为一个,就成了单例
*/
public enum Singleton2 {
INSTANCE
}
//测试代码
public class tesT {
public static void main(String[] args) {
Singleton1 s = Singleton1.INSTANCE;//不是new出来的,直接调用这个实例
System.out.println(s);
Singleton2 s2 = Singleton2.INSTANCE;
System.out.println(s2);
}
}
输出结果:
yu.practiceLeetCode02.Singlenton.Singleton1@10f87f48
INSTANCE
枚举类型重写了toString 方法
public class Singleton3 {
//构造器私有化
private Singleton3(){
}
//创建唯一实例--类初始化的时候就立即加载该实例
private static Singleton3 instance = new Singleton3();
//向外提供该实例--方法二,利用getter()方法
//由于没有存在并发问题,因此不用加synchronized修饰,效率高
public static Singleton3 getter(){
return instance;
}
}
class Singleton3Test{
public static void main(String[] args) {
//不能new
//通过get方法来得到
Singleton3 instance = Singleton3.getter();
Singleton3 instance2 = Singleton3.getter();
System.out.println(instance);
System.out.println(instance2);
System.out.println(instance == instance2);
}
}
懒汉式
懒汉式,延迟创建对象,保证线程安全,又实现了懒加载,但是效率比较低
/*
懒汉式:在类初始化时,并不立即加载该对象,为了避免当该对象长期不被调用时,占内存空间较大;
只有当调用getInstance()方法时,才加载该对象;
而且当instance不是null时,第二次就直接返回instance了,不再new
*/
public class Singleton4 {
//构造器私有化
private Singleton4(){
}
//类初始化时,不立即加载该对象
private static Singleton4 instance ;
//向外提供获取该对象的方法,
//为了避免多线程同时进入该方法,造成负载较大,用synchronized,效率低
public static synchronized Singleton4 getInstance(){
if(instance == null) instance = new Singleton4();
return instance;
}
}</