定义
一个类只允许有一个对象
,
建立一个全局的访问点
,
提供出去供大家使用
.
分析
:
1.
我们肯定要建立一个单例类来描述
2.
只允许有一个对象
3.
全局的访问点
:
说的就是当前的
s
----
通过
static
实现的
4.
提供出去
5.
给大家使用
总括
:1.
传值
.
作为全局的访问点
.
解决一个全局使用的类,频繁创建和销毁。拥有对象的唯一性,并保证内存中对象的唯一。
可以节省内存,因为单例共用一个实例,有利于
Java
的垃圾回收机制。也就是控制资源使
用,通过线程同步来控制资源的并发访问;
控制实例产生的数量,达到节约资源的目的;
使用场景
1.
统计当前在线人数(网站计数器):用一个全局对象来记录。
2.
打印机(设备管理器):当有两台打印机,在输出同一个文件的时候只一台打印机进行输
出。
3.
数据库连接池(控制资源):一般是采用单例模式,因为数据库连接是一种连接数据库资
源,不易频繁创建和销毁。
数据库软件系统中使用数据库连接池,主要是节省打开或者关闭数据库连接所引起的效率损
耗,这种效率的损耗还是非常昂贵的,因此用单例模式来维护,就可以大大降低这种损耗。
4.
应用程序的日志(资源共享):一般日志内容是共享操作,需要在后面不断写入内容所以通
常单例设计。
示例代码:
/*
1.我们肯定要建立一个单例类来描述
2.只允许有一个对象
3.全局的访问点:说的就是当前的s----通过static实现的
4.提供出去
5.给大家使用
*/
public class Demo {
public static void main(String[] args) {
// SingleInstance singleInstance1=new SingleInstance();
// SingleInstance singleInstance2=new SingleInstance();
// System.out.println(singleInstance1==singleInstance2);//false
//通过公共方法找单例对象
SingleInstance singleInstance1 = SingleInstance.getSingleInstance();
SingleInstance singleInstance2 = SingleInstance.getSingleInstance();
System.out.println(singleInstance1 == singleInstance2);//true
//实现功能:有A,B类
//在A类中有属性num1 B类中有属性num2
//num1的值是4,
//
A a=new A();
a.num1=4;
}
static class A{
int num1;
}
static class B{
int num2;
}
}
//饿汉式:在声明SingleInstance变量时直接赋值
class SingleInstance {
//2.生成一个静态的私有的SingleInstance(私有保证有唯一的对象)
//不加final,引用后面的地址可以改变,加final后singleInstance的引用变成了常量,地址不能改变了
//private 目的是为了外界不能访问,改变singleInstance地址(加上final后可以去掉一般习惯性写上)
private final static SingleInstance singleInstance = new SingleInstance();
//1.将构造方法私有化
private SingleInstance() {
}
//3.静态的公共的方法
public static SingleInstance getSingleInstance() {
return singleInstance;
}
//4.重写clone方法,让这个方法也返回当前的单例类的唯一对象
//注意:这个方法一般可以不写
@Override
protected Object clone() throws CloneNotSupportedException {
return singleInstance;
}
}
//懒汉式:在声明SingleInstance1变量时先不进行赋值,等到实际使用的时候在完成赋值
class SingleInstance1 {
//2.生成一个静态的私有的SingleInstance(私有保证有唯一的对象)
private static SingleInstance1 singleInstance1 = null;
//1.将构造方法私有化
private SingleInstance1() {
}
//3.静态的公共的方法
public static SingleInstance1 getSingleInstance1() {
//外层if 减少了synchronized判断的次数,在保证同步的前提下,提高了到哪里使用的效率
if (singleInstance1 == null){//控制不了同步,减少同步判断的次数
synchronized (SingleInstance.class) {//用当前类的字节码文件对象作为锁
if (singleInstance1 == null) {
singleInstance1 = new SingleInstance1();
}
}
}
return singleInstance1;
}
//4.重写clone方法,让这个方法也返回当前的单例类的唯一对象
//注意:这个方法一般可以不写
@Override
protected Object clone() throws CloneNotSupportedException {
return singleInstance1;
}
}
案例:
有一个订单文件order.txt
orderid:20 ordername:shoes orderprice:1000 orderday:1990-10-10
orderid:21 ordername:phones orderprice:1100 orderday:1990-11-10
orderid:17 ordername:computers orderprice:1300 orderday:1990-12-11
1.需要将数据存入List<Order>
2.将list存入单例对象,使其在全局可见
3.对list所在的单例进行序列化操作,并反序列化测试
/*
有一个订单文件order.txt
orderid:20 ordername:shoes orderprice:1000 orderday:1990-10-10
orderid:21 ordername:phones orderprice:1100 orderday:1990-11-10
orderid:17 ordername:computers orderprice:1300 orderday:1990-12-11
1.需要将数据存入List<Order>
2.将list存入单例对象,使其在全局可见
3.对list所在的单例进行序列化操作,并反序列化测试
分析:
IO流
NIO流
集合
面向对象
单例设计模式
序列化/反序列化
*/
public class test {
public static void main(String[] args) {
//1.需要将数据存入List<Order>
List<Order> list=getDate();
System.out.println(list);
//2.将list存入单例对象,使其在全局可见
SinleInstance s=SinleInstance.getInstance();
s.list=list;
test();
//3.对list所在的单例进行序列化操作,并反序列化测试
//writeToFile();
readFromFile();
}
//1.需要将数据存入List<Order>
public static List<Order> getDate(){
List<Order> list1=new ArrayList<>();
try {
List<String> list = Files.readAllLines(Paths.get("C:\\Desktop\\order.txt"));
//将数据转存到Order
for (String s: list) {
list1.add(new Order(s));
}
} catch (IOException e) {
e.printStackTrace();
}
return list1;
}
static public class Order implements Serializable{
private String orderid;
private String ordername;
private double orderprice;
private Date orderday;
public String getOrderid() {
return orderid;
}
public void setOrderid(String orderid) {
this.orderid = orderid;
}
public String getOrdername() {
return ordername;
}
public void setOrdername(String ordername) {
this.ordername = ordername;
}
public double getOrderprice() {
return orderprice;
}
public void setOrderprice(double orderprice) {
this.orderprice = orderprice;
}
public Date getOrderday() {
return orderday;
}
public void setOrderday(Date orderday) {
this.orderday = orderday;
}
public Order(){}
public Order(String orderid, String ordername, double orderprice, Date orderday) {
this.orderid = orderid;
this.ordername = ordername;
this.orderprice = orderprice;
this.orderday = orderday;
}
@Override
public String toString() {
return "Order{" +
"orderid=" + orderid +
", ordername='" + ordername + '\'' +
", orderprice=" + orderprice +
", orderday='" + orderday + '\'' +
'}';
}
//完成数据切割
public Order(String src){
String[] srcs=src.split("\t");
for (String s : srcs) {
String[] pair=s.split(":");
//去空格
String key=pair[0].trim();
String value=pair[1].trim();
//正则表达式
if (key.equals("orderid")){
this.orderid=value;
}else if (key.equals("ordername")){
this.ordername=value;
}else if (key.equals("orderprice")){
this.orderprice= Double.parseDouble(value);
}else if (key.equals("orderday")){
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
try {
this.orderday = simpleDateFormat.parse(value);
} catch (ParseException e) {
e.printStackTrace();
}
}
}
}
}
//2.将list存入单例对象,使其在全局可见
public static void test(){
SinleInstance s=SinleInstance.getInstance();
System.out.println("单例对象中的list"+s.list);
}
//3.对list所在的单例进行序列化操作,并反序列化测试
public static void writeToFile(){
try(ObjectOutputStream objectOutputStream=new ObjectOutputStream(new FileOutputStream("0609--单例\\danli.txt"))){
objectOutputStream.writeObject(SinleInstance.getInstance());
} catch (IOException e) {
e.printStackTrace();
}
}
public static void readFromFile(){
try(ObjectInputStream objectInputStream=new ObjectInputStream(new FileInputStream("0609--单例\\danli.txt"))) {
try {
SinleInstance s=(SinleInstance)objectInputStream.readObject();
System.out.println("逆序列化后的list:"+s.list);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
//单例类
class SinleInstance implements Serializable {
private static final long serialVersionUID=-2848937489372589732L;
private static SinleInstance s=null;
private SinleInstance(){}
public static SinleInstance getInstance(){
if (s==null){
synchronized (SinleInstance.class){
if (s==null){
s=new SinleInstance();
}
}
}
return s;
}
//功能区
List<test.Order> list=new ArrayList<>();
}
注意:要把单例单独一写一个类出来,不要写在类里。
例如:
/阿里总裁到广州,北京,上海访问
//总裁属性:姓名,年龄,性别
//要求:使用单例实现
//阿里总裁到广州,北京,上海访问
//总裁属性:姓名,年龄,性别
//要求:使用单例实现
public class homework {
public static void main(String[] args) {
visitBeijing();
visitGuangzhou();
visitShanghai();
}
public static void visitGuangzhou(){
SingleInstance singleInstance = SingleInstance.getS();
System.out.println("总裁"+singleInstance.president.getName()+"到广州开会");
}
public static void visitBeijing(){
SingleInstance singleInstance = SingleInstance.getS();
System.out.println("总裁"+singleInstance.president.getName()+"到北京开会");
}
public static void visitShanghai(){
SingleInstance singleInstance = SingleInstance.getS();
System.out.println("总裁"+singleInstance.president.getName()+"到上海开会");
}
}
enum Gender{
Male,FeMale
}
class President{
private String name;
private int age;
private Gender gender;
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 Gender getGender() {
return gender;
}
public void setGender(Gender gender) {
this.gender = gender;
}
public President(String name, int age, Gender gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
}
class SingleInstance{
private static SingleInstance s = null; private SingleInstance(){}
public static SingleInstance getS() {
if (s == null){
synchronized (SingleInstance.class){
if (s == null){ s = new SingleInstance();
}
}
}
return s;
}
President president = new President("云云",40,Gender.Male);
}