13.单例设计模式
采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只能提供一个取得其对象实例的方法
饿汉式(不使用该实例时就创建,可能创建了但不使用,造成资源的浪费):
-
构造器私有化(防止用户直接new)
-
类的内部创建对象
-
向外暴露一个静态的公共方法 getinstance
-
代码实现
public class HelloJava { public static void main(String[] args) { //通过方法可以获取对象 GirlFriend instance = GirlFriend.getInstance(); System.out.println(instance); } } //有一个类,GirlFriend //只能有一个女朋友 class GirlFriend{ private String name; //如果不在此处加static,那么下面的公共的静态方法就无法调用这个对象 private static GirlFriend gf = new GirlFriend("章若楠"); //如何保证只能创建一个GrilFriend对象呢 //步骤[单例模式-饿汉式] //1.将构造器私有化 //2.在类的内部直接创建 //3.提供一个公共的静态方法,返回ge对象 private GirlFriend(String name) { this.name = name; } public static GirlFriend getInstance(){ return gf; } @Override public String toString() { return "GirlFriend{" + "name='" + name + '\'' + '}'; } }
懒汉式(使用了再创建该实例):
-
构造器私有化
-
定义一个静态属性对象
-
提供一个公共的静态方法,可以返回一个Cat对象
-
只有当用户使用getInstance时,才返回Cat对象,后面再次调用时,会返回上个创建的对象
public class HelloJava { public static void main(String[] args) { //通过方法可以获取对象 Cat instance = Cat.getInstance(); System.out.println(instance); } } //希望在程序运行的过程中,只能创建一个Cat对象 //使用单例模式 class Cat{ private String name; private static Cat cat; //步骤 //1.构造器私有化 //2.定义一个静态属性对象 //3.提供一个公共的静态方法,可以返回一个Cat对象 //4.懒汉式,只有当用户使用getInstance时,才返回cat对象,后面再次调用时,会返回上个创建的对象 // 从而保证了单例 private Cat(String name) { this.name = name; } public static Cat getInstance(){ if (cat == null){ cat = new Cat("汤圆"); } return cat; } @Override public String toString() { return "Cat{" + "name='" + name + '\'' + '}'; } }
饿汉式VS懒汉式
-
二者最主要的区别在于创建对象的时机不同
-
饿汉式不存在线程安全问题,懒汉式存在线程安全问题
-
饿汉式存在浪费资源的可能,懒汉式不存在这个问题
-
在javaSE标准类中,java.lang.Runtime就是单例模式
14.final基本使用
以下情况就会用到final:
-
当不希望类被继承时,可以用final修饰
-
当不希望父类的某个方法被子类覆盖/重写时,可以用final修饰
-
当不希望类的某个属性的值被修改,可以用final修饰
-
当不惜某个局部变量被修改,可以用final修饰
public class HelloJava { public static void main(String[] args) { } } //要求A类不能被其他类继承 final class A{} //要求C类中的hi不能被子类重写 class C{ public final void hi(){} } //当不希望类的某个属性的值被修改,可以用final修饰 class D{ public final double TAX_RATE = 0.08; } //当不惜某个局部变量被修改,可以用final修饰 class E{ public void cry(){ final double NUM = 0.01; } }
15.final使用细节
-
final修饰的属性又叫常量,一般用 XX_XX_XX来命名
-
final修饰的属性在定义时,必须赋初始值,并且以后不能再修改,赋值可能在1.定义时;2.在构造器中;3.在代码块中
-
如果final修饰的属性是静态的,则初始化的位置只能是1.定义时;2.在静态代码块中。不能再构造器中赋值
-
final类不能继承,但是可以实例化对象
-
如果类不是final类,但是含有final方法,则该方法不能重写,但是可以被继承
-
如果一个类已经是final类了,就没有必要再将方法修饰成final方法
-
final不能修饰构造方法(构造器)
-
final和static往往搭配使用,使效率更高,不会导致类加载,底层编译器做了优化处理
-
包装类(Integer,Double,Float,Boolean等都是final),String也是final类
16.final练习
编写一个程序,能够计算圆形的面积,要求圆周率威3.14,赋值的位置3三个方式都写一下
public class HelloJava { public static void main(String[] args) { Circle circle = new Circle(5.0); System.out.println("面积=" + circle.calArea()); } } class Circle{ private double radius; private final double PI = 3.14; //构造器 public Circle(double radius) { this.radius = radius; // PI = 3.14; } //代码块 //{ // PI = 3.14; //} public double calArea(){ return PI * radius * radius; } }