Java设计模式系列(一):单例模式&原型模式

单例模式(Singleton)-4

懒汉-线程不安全

public class LazySingleton {
    private static LazySingleton lazySingleton = null;

    private LazySingleton() {
    }

    /**
     * 线程不安全
     */
    public static LazySingleton getInstance() {
        if (lazySingleton == null) {
            lazySingleton = new LazySingleton();
        }
        return lazySingleton;
    }
}

加锁保证线程安全:在静态方法中直接加锁,并发性能不好。

public static LazySingleton getInstance(){
    synchronized (LazySingleton.class){
        if(lazySingleton==null){
            lazySingleton = new LazySingleton();
        }
        return lazySingleton;
    }
}

懒汉-线程安全-double check+volatile

提高并发性能

private volatile static LazySingleton lazySingleton = null;
public static LazySingleton getInstance(){
    if(lazySingleton==null){
        synchronized (LazySingleton.class){
            if(lazySingleton==null){
                lazySingleton = new LazySingleton();
            }
        }
    }
    return lazySingleton;
}

懒汉-线程安全-静态内部类

原理:静态内部类在使用时才加载,不过在加载静态内部类的过程中也会加载外部类,静态内部类有个初始化锁,且初始化只会执行一次,因此线程安全

public class LazyInnerSingleton {
    public static class InnerClass{
        private static LazyInnerSingleton lazyInnerSingleton = new LazyInnerSingleton();
    }
    
    private LazyInnerSingleton() {
    }
    
    public static LazyInnerSingleton getInstance(){
        return InnerClass.lazyInnerSingleton;
    }
}

饿汉-线程安全

立即加载

public class HangrySingleton {
    // final修饰后,在类加载的时候就完成赋值,之后不能改变
//    private final static HangrySingleton hangrySingleton = new HangrySingleton();

    // 静态代码块方式
    private final static HangrySingleton hangrySingleton;
    static {
        hangrySingleton = new HangrySingleton();
    }

    private HangrySingleton() {
    }

    public static HangrySingleton getInstance(){
        return hangrySingleton;
    }
}

原型模式(Prototype )-5

  1. 用于创建重复的对象,同时又能保证性能。当直接创建对象的代价比较大时,则采用这种模式。
  2. 实现Cloneable接口,需要重写clone()方法,克隆不调用构造器

使用案例

@Data
public class Pig implements Cloneable{
    public Pig(String name, Date birthday) {
        this();

        this.name = name;
        this.birthday = birthday;
    }

    public Pig() {
        System.out.println("对象初始化,步骤多,代价很大...");
    }

    private String name;
    private Date birthday;

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

test

@Test
public void test05() throws CloneNotSupportedException {
    Date date = new Date(0);
    Pig pigInit = new Pig("pig0",date);
    for (int i = 0; i < 10; i++) {
        Pig pigTemp = (Pig) pigInit.clone();
        pigTemp.setName("pig"+i);
        pigTemp.setBirthday(new Date());
        System.out.println(pigTemp);
    }
    System.out.println("保存初始值:"+pigInit);
}

打印:

对象初始化,步骤多,代价很大...
Pig(name=pig0, birthday=Thu Jun 04 21:49:39 CST 2020)
...
Pig(name=pig8, birthday=Thu Jun 04 21:49:39 CST 2020)
Pig(name=pig9, birthday=Thu Jun 04 21:49:39 CST 2020)
保存初始值:Pig(name=pig0, birthday=Thu Jan 01 08:00:00 CST 1970)

浅克隆引发的问题

默认浅克隆

浅拷贝引发的问题:
克隆后的对象,虽然对象地址不同,但是其属性是指向同一个引用

@Test
public void test06() throws CloneNotSupportedException {
    Date birth = new Date(0L);
    Pig pig0 = new Pig("佩奇",birth);
    Pig pig1 = (Pig) pig0.clone();

    System.out.println(pig0);
    System.out.println(pig1);

    // 修改引用类型的属性
    pig0.getBirthday().setTime(666666666666L);

    System.out.println(pig0);
    System.out.println(pig1);
}

打印:

对象初始化,步骤多,代价很大...
mxx.design.pattern.creational.prototype.Pig@25f38edcPig{name='佩奇', birthday=Thu Jan 01 08:00:00 CST 1970}
mxx.design.pattern.creational.prototype.Pig@3eb07fd3Pig{name='佩奇', birthday=Thu Jan 01 08:00:00 CST 1970}
mxx.design.pattern.creational.prototype.Pig@25f38edcPig{name='佩奇', birthday=Sat Feb 16 09:11:06 CST 1991}
mxx.design.pattern.creational.prototype.Pig@3eb07fd3Pig{name='佩奇', birthday=Sat Feb 16 09:11:06 CST 1991}

pig1的birthday也被修改了。这里需要将该字段变成深克隆

深克隆

在clone方法里对需要深克隆的属性单独克隆

 @Override
public Object clone() throws CloneNotSupportedException {
    Pig pig =  (Pig) super.clone();
    pig.birthday = (Date) pig.birthday.clone();
    return pig;
}

打印

对象初始化,步骤多,代价很大...
mxx.design.pattern.creational.prototype.Pig@25f38edcPig{name='佩奇', birthday=Thu Jan 01 08:00:00 CST 1970}
mxx.design.pattern.creational.prototype.Pig@3eb07fd3Pig{name='佩奇', birthday=Thu Jan 01 08:00:00 CST 1970}
mxx.design.pattern.creational.prototype.Pig@25f38edcPig{name='佩奇', birthday=Sat Feb 16 09:11:06 CST 1991}
mxx.design.pattern.creational.prototype.Pig@3eb07fd3Pig{name='佩奇', birthday=Thu Jan 01 08:00:00 CST 1970}

深克隆后,pig1的birthday没有被修改

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值