头图

每天5分钟-创建型模式(二)

这篇就是设计模式的最后一篇文章了,写的非常简洁,基本上是通过例子来解释模式。虽然并没有很深挖,但是如果能帮到你们理解到是什么这个地步我觉得就够了。

下一个系列的话,大概率是spring全家桶这方面的,也有可能是其它方面的。

单例模式

单例模式应该算是最常用的设计模式了叭,著名的双重校验也是单例模式的一种实现。所谓单例模式就是用来保证一个对象只能创建一个实例,除此之外,它还提供了对实例的全局访问方式。

单例模式UML类图

单例模式饿汉式

所谓饿汉式,人饿了看到啥都想吃。同样,不管需不需要这个实例,反正我都先给你创建好。

普通实现

public class SingletonHungry {
    
    //在类加载的时候就已经创建了唯一的实例
    private static final SingletonHungry instance = new SingletonHungry();
    
    //保证外部不能调用构造函数
    private SingletonHungry() {
    }

    //外部调用这个方法,就返回实例
    public static SingletonHungry getInstance() {
        return instance;
    }
    
    //类中其它方法,尽量是static
    public static void func(){}
    
}

静态代码块

public class SingletonHungryStatic {
    //其实就是把new的部分移到了静态代码块中
    private static SingletonHungryStatic instance = null;
    static {
        instance = new SingletonHungryStatic();
    }

    private SingletonHungryStatic() {
    }

    public static SingletonHungryStatic getInstance() {
        return instance;
    }

    //类中其它方法,尽量是static
    public static void func(){}
}

单例模式懒汉式

所谓懒汉,就是要不是有人催促,就不肯去劳动。同理,只有你找我要这个是,才创建出来。

普通实现

public class SingletonLazy {
    //volatile之前已经讲过,防止指令的重排序,这个volatile是不能省略的
    private static volatile SingletonLazy instance = null;
    private SingletonLazy(){}

    public static SingletonLazy getInstance() throws Exception {

        if(instance == null) {
            synchronized (SingletonLazy.class) {
                if(instance == null) {
                    instance = new SingletonLazy();
                }
            }
        }
        return instance;
    }
}

静态内部类

public class SingletonLazyStatic {
    
    /**
     * 静态内部类注意事项
     *  1. 类加载的时,静态内部类不会随着加载
     *  2. 静态内部类只会初始化一次
     *  3. 线程安全的
     */
    
    private static class StaticClassInstance{
        private static final SingletonLazyStatic INSTACE = new SingletonLazyStatic();
    }
    private SingletonLazyStatic() {
    }
    
    public static SingletonLazyStatic getInstance() {
        return StaticClassInstance.INSTACE;
    }
}

其实还有一种更为优雅的实现方式,那就是使用枚举,不过之前看那些文章好像都说什么少用,所以本文就不粘出来给各位增加学习成本了。

Client

public class Client {
    public static void main(String[] args) throws Exception {
//        hungry();
//        hungryStatic();
//        lazy();
        lazyStatic();
    }

    public static void lazyStatic() {
        SingletonLazyStatic instance = SingletonLazyStatic.getInstance();
        SingletonLazyStatic instance1 = SingletonLazyStatic.getInstance();
        System.out.println(instance);
        System.out.println(instance1);
    }
    
    //下面3中和上面实现是类似的,只需要更换类名
    public static void lazy() throws Exception {}

    public static void hungry() {}

    public static void hungryStatic() {}

}

原型模式

原型模式听起来高大上,其实就是一种克隆对象的方法。

说到克隆不得不简单说下浅拷贝和深拷贝,浅拷贝就是指两个指针指向了同一个对象,原对象和拷贝对象只要有一个修改,另外一个也随着修改。深拷贝是指,重新创建了一个和原对象一模一样内容的拷贝对象,两者是独立的。基本数据类型是不参与拷贝过程的

Prototype: 抽象原型类,声明了clone方法的接口或者基类,其中clone方法必须由派生对象实现。

Concrete Prototype: 具体实现类,主要是用于实现或扩展clone方法的类。

原型模式UML类图

原型模式

Prototype

public abstract class PrototypePhone implements Cloneable {
    private String cpu;
    private int price;

    @Override
    public  Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
    
    //省略构造函数,get,set方法

}

Concrete Prototype

public class ConcretePrototypeOnePlus extends PrototypePhone {
    public ConcretePrototypeOnePlus(String cpu, int price) {
        super(cpu, price);
        System.out.println("调用了构造函数");
    }

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

Client

public class Client {
    public static void main(String[] args) throws CloneNotSupportedException {
        PrototypePhone phone = new ConcretePrototypeOnePlus("865", 3999);
        System.out.println("原型:" + phone);
        for (int i = 0; i < 100; i++) {
            System.out.println("生产第" + (i + 1) + "台手机:" + phone.clone());
        }
    }
}

运行的话就会发现构建的手机只通过了一次构造函数,其它的使用phone.clone() 也能同样构造出手机实例对象。

3 声望
0 粉丝
0 条评论
推荐阅读
初窥函数式接口,不会取标题,没有噱头,全是干货
An Interface that contains exactly one abstract method is known as functional interface. It can have any number of default, static methods but can contain only one abstract method. It can also decl...

cutey_none阅读 118

Spring事务传播行为详解
Spring在TransactionDefinition接口中规定了7种类型的事务传播行为。事务传播行为是Spring框架独有的事务增强特性,他不属于的事务实际提供方数据库行为。这是Spring为我们提供的强大的工具箱,使用事务传播行可...

JerryTse242阅读 122.7k评论 97

从零搭建 Node.js 企业级 Web 服务器(十五):总结与展望
总结截止到本章 “从零搭建 Node.js 企业级 Web 服务器” 主题共计 16 章内容就更新完毕了,回顾第零章曾写道:搭建一个 Node.js 企业级 Web 服务器并非难事,只是必须做好几个关键事项这几件必须做好的关键事项就...

乌柏木75阅读 7.1k评论 16

从零搭建 Node.js 企业级 Web 服务器(一):接口与分层
分层规范从本章起,正式进入企业级 Web 服务器核心内容。通常,一块完整的业务逻辑是由视图层、控制层、服务层、模型层共同定义与实现的,如下图:从上至下,抽象层次逐渐加深。从下至上,业务细节逐渐清晰。视图...

乌柏木45阅读 8.5k评论 6

从零搭建 Node.js 企业级 Web 服务器(二):校验
校验就是对输入条件的约束,避免无效的输入引起异常。Web 系统的用户输入主要为编辑与提交各类表单,一方面校验要做在编辑表单字段与提交的时候,另一方面接收表单的接口也要做足校验行为,通过前后端共同控制输...

乌柏木35阅读 6.7k评论 10

一文搞懂秒杀系统,欢迎参与开源,提交PR,提高竞争力。早日上岸,升职加薪。
前言秒杀和高并发是面试的高频考点,也是我们做电商项目必知必会的场景。欢迎大家参与我们的开源项目,提交PR,提高竞争力。早日上岸,升职加薪。知识点详解秒杀系统架构图秒杀流程图秒杀系统设计这篇文章一万多...

王中阳Go33阅读 2.5k评论 1

封面图
从零搭建 Node.js 企业级 Web 服务器(五):数据库访问
回顾 从零搭建 Node.js 企业级 Web 服务器(一):接口与分层,一块完整的业务逻辑是由视图层、控制层、服务层、模型层共同定义与实现的,控制层与服务层实现了业务处理过程,模型层定义了业务实体并以 对象-关系...

乌柏木34阅读 5k评论 9

3 声望
0 粉丝
宣传栏