笨蛋学设计模式创建者模式-单例模式【2】
2024-01-08 20:26:15
创建者模式-单例模式
6.1单例模式??????
6.1.1概念
? 单例模式确保一个类只有一个实例,并提供一个全局访问点来访问该实例,通常用于需要频繁创建和销毁同一对象的场景,以避免资源浪费和提高性能。
6.1.2场景
? 我们只有一个大脑,但是我们需要频繁地使用它来思考、记忆和判断。如果我们每次需要使用大脑时都重新创建一个新的大脑,那么就会浪费时间以及其他资源。因此,我们只需要一个大脑实例,并通过全局访问点(例如我们的嘴巴和眼睛)来使用它。
6.1.3优势 / 劣势
- 全局访问点:确保所有对象都能访问到唯一实例,避免了创建多个对象实例
- 线程安全:单例模式可以保证线程安全,避免多线程下对共享资源的竞争问题,确保数据一致性和线程安全性
- 资源节省:确保程序中存在一个实例,避免了多次创建和销毁同一对象,减少了系统资源的浪费
- 过度依赖单例:可能会导致各个模块之间的耦合度过高,不利于代码的模块化和可维护性
- 不适用多实例场景:若需要多个实例来执行不同的任务,就无法满足任务
- 生命周期过长:单例模式的生命周期往往贯穿整个应用程序的始终,可能会导致一些其他问题
6.1.4满足单例模式的基本要求
6.1.5饿汉式
- 在类加载时就已经完成了实例的创建,不管后面创建的实例有没有使用,先创建再说,所以称之为饿汉
public class Hungry {
private static final Hungry instance = new Hungry();
private Hungry(){
//私有化构造方法,防止外部实例化
}
public static Hungry getInstance(){
return instance;
}
}
6.1.6懒汉式
- 在请求实例时才会创建,若在首次请求时还没有创建,就创建一个新的实例,若已经创建就返回已有的实例,需要使用再创建,所以称之为懒汉
public class Lazy {
private static Lazy instance;
private Lazy(){
//私有化构造方法,防止外部实例化
}
public static synchronized Lazy getInstance(){
if(instance == null){
instance = new Lazy();
}
return instance;
}
}
6.1.7懒汉式+双重检查锁
public class LazyAndLock {
private static volatile LazyAndLock instance;
private LazyAndLock(){
//私有构造方法,防止外部实例化
}
public static LazyAndLock getInstance(){
if(instance == null){
//LazyAndLock.class作为同步锁对象,保证多线程环境下只有一个线程进入同步块内部创建对象
synchronized (LazyAndLock.class){
if(instance == null){
instance = new LazyAndLock();
}
}
}
return instance;
}
}
6.1.8实战
6.1.8.1题目描述
小明去了一家大型商场,拿到了一个购物车,并开始购物。请你设计一个购物车管理器,记录商品添加到购物车的信息(商品名称和购买数量),并在购买结束后打印出商品清单。(在整个购物过程中,小明只有一个购物车实例存在)。
6.1.8.2输入描述
输入包含若干行,每行包含两部分信息,分别是商品名称和购买数量。商品名称和购买数量之间用空格隔开。
6.1.8.3输出描述
输出包含小明购物车中的所有商品及其购买数量。每行输出一种商品的信息,格式为 “商品名称 购买数量”。
6.1.5.4代码
饿汉式
package com.designpattern.mode.singleton;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
public class Test {
public static void main(String[] args) {
HungryShoppingCartManager cart = HungryShoppingCartManager.getInstance();
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()){
String goods = scanner.next();
int goodsNum = scanner.nextInt();
//添加到购物车
cart.addCart(goods,goodsNum);
}
// cart.delCart("apple");
//
// cart.updCart("banana",3);
//查找所有的商品
cart.selCart();
}
}
class HungryShoppingCartManager{
//使用购物车前就创建
private static HungryShoppingCartManager instance=new HungryShoppingCartManager();
//定义购物车存放商品及对应的数量
private Map<String,Integer> cart;
private HungryShoppingCartManager(){
//私有化构造方法,防止外部实例化
cart = new LinkedHashMap<>();
}
public static HungryShoppingCartManager getInstance(){
return instance;
}
//定义添加方法
public void addCart(String goods,int goodsNum){
//getOrDefault(goods, 0) 方法获取该物品的数量,如果获取不到则返回默认值 0
cart.put(goods,cart.getOrDefault(goods,0)+goodsNum);
}
//定义删除方法
public void delCart(String goods){
cart.remove(goods);
}
//定义修改方法
public void updCart(String goods,int goodsNum){
cart.put(goods,goodsNum);
}
//定义查找方法
public void selCart(){
Set<Map.Entry<String, Integer>> entrySet = cart.entrySet();
for (Map.Entry<String, Integer> entry : entrySet) {
String key = entry.getKey();
int value = entry.getValue();
System.out.println(key+"-"+value);
}
}
}
懒汉式+双重检查锁
package com.designpattern.mode.singleton;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
public class Test {
public static void main(String[] args) {
LazyShoppingCartManager cart = LazyShoppingCartManager.getInstance();
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()){
String goods = scanner.next();
int goodsNum = scanner.nextInt();
//添加到购物车
cart.addCart(goods,goodsNum);
}
// cart.delCart("apple");
//
// cart.updCart("banana",3);
//查找所有的商品
cart.selCart();
}
}
class LazyShoppingCartManager{
private static LazyShoppingCartManager instance;
//购物车存放商品及对应数量
private Map<String,Integer> cart;
//私有化构造函数
private LazyShoppingCartManager(){
cart = new LinkedHashMap<>();
}
//获取购物车实例
public static synchronized LazyShoppingCartManager getInstance(){
if(instance == null){
synchronized (LazyShoppingCartManager.class){
if(instance == null){
instance = new LazyShoppingCartManager();
}
}
}
return instance;
}
//定义添加方法
public void addCart(String goods,int goodsNum){
//getOrDefault(goods, 0) 方法获取该物品的数量,如果获取不到则返回默认值 0
cart.put(goods,cart.getOrDefault(goods,0)+goodsNum);
}
//定义删除方法
public void delCart(String goods){
cart.remove(goods);
}
//定义修改方法
public void updCart(String goods,int goodsNum){
cart.put(goods,goodsNum);
}
//定义查找方法
public void selCart(){
Set<Map.Entry<String, Integer>> entrySet = cart.entrySet();
for (Map.Entry<String, Integer> entry : entrySet) {
String key = entry.getKey();
int value = entry.getValue();
System.out.println(key+"-"+value);
}
}
}
6.1.9总结
优点:在类加载时就完成了初始化,避免了线程同步的问题,是最安全的单例模式实现方式
总结:在类加载时就实例化了一个对象,所以类加载较慢,但获取对象的速度快
场景:主要用于线程安全的场景
优点:只有在需要对象时才会进行实例化,具有更好的灵活性。
总结:在类加载时不进行实例化,当调用getInstance方法时才进行实例化。
场景:主要用于线程不安全的场景,可以使用双重检查锁定等方法来保证线程安全。
文章来源:https://blog.csdn.net/YSL_Monet/article/details/135443984
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!