设计模式-单例模式(唯一的月亮实例附代码)

单例模式简介

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

注意:

1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。

单例模式结构

单例模式是关于怎样设计一个类,并使得该类只有一个实例的成熟模式,该模式的关键是将类的构造方法设置为private权限,并提供一个返回它的唯一实例的类方法。
在这里插入图片描述

使用场景:

1、要求生产唯一序列号。
2、WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。
3、创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。

优点:

1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。
2、避免对资源的多重占用(比如写文件操作)。

缺点:

没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。

注意事项:

getInstance() 方法中需要使用同步锁 synchronized (Singleton.class) 防止多线程同时进入造成 instance 被多次实例化。

单例模式懒汉和饿汉实现

(1)懒汉实现

package single;
/**单例模式练习 :
 * 
1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。
三大特点:私有构造函数,静态私有成员变量,静态的共有的工厂方法。
*/
/**对于懒汉类型的安全隐患,多个线程同时访问将导致创建多个对象,该怎么办? 
 * 多线程会创建不同的对象,就有不同的单例对象
 * 多线程访问同一个资源的安全问题,而单线程就不会
*/
public class Simplesgl {
    //懒汉类型
    //根据类型进行初始化,引用类型返回null,并且只能是static
    private static Simplesgl instance=null;//这里是引用类型
    //定义为private
    private Simplesgl(){

    }
    /**不同的线程会创建不同的对象 
     * 所以对线程进行加锁synchronized
    */
    public synchronized static Simplesgl newInstance(){
        //进行创建唯一的对象,因为引用类型返回值为null
        if(instance==null){
            try {
                //创建线程类
                //Thread.sleep(new Random().nextInt(1000));
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            instance=new Simplesgl();
        }
        return instance;
    }

}

(2)饿汉实现

package single;
/**单例模式练习 :
 * 
1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。
三大特点:私有构造函数,静态私有成员变量,静态的共有的工厂方法。
*/
public class Simplesgl2{
    //饿汉类型
    //根据类型进行初始化,引用类型返回null,并且只能是static
    private static Simplesgl2 instance=new Simplesgl2();//这里是引用类型
    //定义为private
    private Simplesgl2(){

    }
    public static Simplesgl2 newInstance(){
        //进行创建唯一的对象,因为引用类型返回值为null
        // if(instance==null){
        //     instance=new Simplesgl();
        // }
        return instance;
    }

}

(3)测试类

package single;

public class TestSingle {
    public static void main(String[] args) {
        //单例模式:永远就只是创建一个对象。
        // Simplesgl sgl =new Simplesgl();
        // Simplesgl sgl2=new Simplesgl();
        Simplesgl sgl =Simplesgl.newInstance();
        //Simplesgl sgl2=null;
        // Simplesgl sgl2=Simplesgl.newInstance();
        // Simplesgl sgl3=Simplesgl.newInstance();
        System.out.println("*******------------*********");
        new Thread(
            //lambda表达式()->{}自动推导
            ()->{
                Simplesgl sgl2=Simplesgl.newInstance();
                System.out.println("lambda----sgl2:"+sgl2);
            }
        ).start();
        for(int i=0;i<20;i++)
        new Thread(
            //lambda表达式()->{}自动推导
            ()->{
                Simplesgl sgl3=Simplesgl.newInstance();
                System.out.println("lambda----sgl3:"+sgl3);
            }
        ).start();
        System.out.println(sgl);
        // System.out.println(sgl2);
        // System.out.println(sgl3);


    }
    
}

案例实现

简介:用单例模式实现唯一的月亮。
(1)Moon类

package single;
/** 
 * 单例类(单件类):确保一个类只有一个实例
*/

public class Moon {
    private static Moon uniqueMoon;//定义唯一的月亮
    double radius;//定义月亮的半径
    double distanceToEarth;//定义月亮的距离
    //定义私有的构造方法,该类不会被实例化
    private Moon() {
        uniqueMoon = this;
        radius = 1738;//月球的半径
        distanceToEarth = 363300;//月球距地球的距离
    }
    //该方法是懒汉型,存在安全隐患,要对其加锁synchronized
    public static synchronized Moon getMoon() {
        //进行创建唯一的对象,引用类型返回值为null
        if(uniqueMoon == null) {
            uniqueMoon = new Moon();
        }
        return uniqueMoon;
    }
    //定义一个成员方法,返回信息
    public String show() {
        String s = "月亮的半径是" + radius + "km, 距地球是" + distanceToEarth + "km";
        return s;
    }
}

(2)App类

package single;

import javax.swing.*;
import java.awt.*;
public class App{
    public static void main(String[] args) {
        MyFrame f1 = new MyFrame("张三看月亮");
        MyFrame f2 = new MyFrame("李四看月亮");
        f1.setBounds(10, 10, 360, 150);
        f2.setBounds(370, 10, 360, 150);
        f1.validate();
        f2.validate();
    }
}
class MyFrame extends JFrame {
    String str;
    MyFrame(String title) {
        setTitle(title);
        Moon moon = Moon.getMoon();//得到唯一的月亮
        str = moon.show();//展现信息
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        setVisible(true);
        repaint();
    }
    public void paint(Graphics g) {
        super.paint(g);
        g.setFont(new Font("宋体", Font.BOLD, 14));
        g.drawString(str, 5, 100);
    }
}
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小辉在线

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值