设计模式
是一种编码套路
单例模式
一个类只能创建一个实例
饿汉式
直接创建唯一实例
package com.by.entity;
/**
* 单例模式-饿汉式
*/
public class ClassA {
//static: 1. newClassA可以访问返回 2. 静态属性内存中只会存在一个
//private: 防止外界直接访问属性
private static ClassA ca = new ClassA();
//外界获取唯一实例的渠道
//static:使外界直接通过类名访问
public static ClassA newClassA(){
return ca;
}
//构造私有化-防止外界调用构造创建对象
private ClassA(){
}
}
缺点: 有可能浪费空间
懒汉式
在获取实例是创建唯一对象
package com.by.entity;
/**
* 单例模式-懒汉式
*/
public class ClassB {
//static: 1. newClassA可以访问返回 2. 静态属性内存中只会存在一个
//private: 防止外界直接访问属性
private static ClassB cb = null;
//外界获取唯一实例的渠道
//static:使外界直接通过类名访问
//synchronized: 同步方法 预防线程安全问题
public static synchronized ClassB newClassB(){
if (cb == null) {//当第一次获取时再进行实例化
cb = new ClassB();
}
return cb;
}
//构造私有化-防止外界调用构造创建对象
private ClassB(){
}
}
缺点: 线程效率慢
懒汉式-进阶版
在懒汉式的基础上,利用同步代码块结合二次校验提高执行效率
package com.by.entity;
/**
* 单例模式-懒汉式进阶版
*/
public class ClassC {
//static: 1. newClassA可以访问返回 2. 静态属性内存中只会存在一个
//private: 防止外界直接访问属性
private static ClassC cc = null;
//外界获取唯一实例的渠道
//static:使外界直接通过类名访问
public static ClassC newClassC(){
if (cc == null) {//二次校验: 决定是否需要开启互斥锁 t1:true t2:true
synchronized (ClassC.class) {//临界资源对象: 当前类的类对象
//对属性进行实例化
if (cc == null) {//当第一次获取时再进行实例化
cc = new ClassC();
}
}
}
return cc;
}
//构造私有化-防止外界调用构造创建对象
private ClassC(){
}
}package com.by.entity;
/**
* 单例模式-懒汉式进阶版
*/
public class ClassC {
//static: 1. newClassA可以访问返回 2. 静态属性内存中只会存在一个
//private: 防止外界直接访问属性
private static ClassC cc = null;
//外界获取唯一实例的渠道
//static:使外界直接通过类名访问
public static ClassC newClassC(){
if (cc == null) {//二次校验: 决定是否需要开启互斥锁 t1:true t2:true
synchronized (ClassC.class) {//临界资源对象: 当前类的类对象
//对属性进行实例化
if (cc == null) {//当第一次获取时再进行实例化
cc = new ClassC();
}
}
}
return cc;
}
//构造私有化-防止外界调用构造创建对象
private ClassC(){
}
}
工厂模式
-
是一种底层技术,通常用于底层框架的编写
-
思路: 将数据的创建和维护交由工厂完成
案例
- 需求: 构建一个工厂类,获取学生对象
-
提供学生类
package com.by.entity; public class Student { private String name; private int age; private double score; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public double getScore() { return score; } public void setScore(double score) { this.score = score; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + ", score=" + score + '}'; } public Student() { } public Student(String name, int age, double score) {//string,int,double this.name = name; this.age = age; this.score = score; } }
-
书写配置文件
-
在项目下创建后缀名为
.properties
的配置文件 -
作用: 存放被管理类的全限定名
-
以
键=值
的形式存放数据 -
键值不可添加双引号、末尾不可添加分号、中间不可存在多个符号(如空格)
-
一行只能有一个键值对
StudentClassName=com.by.entity.Student
-
-
书写工厂类
package com.by.util; import com.by.entity.Student; import java.io.FileInputStream; import java.util.Properties; public class MyFactory { /** * 获取学生对象 */ public static Student getStudent(){ Student student = null; try ( //创建输入流 FileInputStream fis=new FileInputStream("factory.properties") ) { //将配置文件的内容加载到集合中 Properties p = new Properties(); p.load(fis); //获取全限定名 String className = p.getProperty("StudentClassName"); //获取类对象 Class c = Class.forName(className); //利用反射构建学生实例 student = (Student) c.newInstance(); } catch (Exception e) { System.out.println("未知异常!"); e.printStackTrace(); } return student; } }
-
测试
package com.by.test; import com.by.entity.Student; import com.by.util.MyFactory; public class Test5 { public static void main(String[] args) { //利用工厂获取学生实例对象 Student s1 = MyFactory.getStudent(); Student s2 = MyFactory.getStudent(); } }