创建型模式
单例模式
一个类只允许创建一个对象,称为单例。
单例体现:配置类、连接池、全局计数器、id生成器、日志对象。
懒汉式
(线程不安全) 单例:【不可用】
用到该单例对象的时候再创建。但存在很大问题,单线程下这段代码没有问题,但是在多线程下有很大问题。
public class LazyMan {
private LazyMan(){};
public static LazyMan lazyMan;
public static LazyMan getInstance(){
if (lazyMan==null){
lazyMan = new LazyMan(); //用到该单例对象的时候再创建,这里没加锁,如果多个线程进入,会并发产生多个实例
}
return lazyMan;
}
}
(线程安全)单例:【不推荐使用】
同步方法
缺点:效率低,每次getInstance时都要同步处理,存在性能问题,实际开发不推荐
public class LazyMan {
private LazyMan(){}; //私有化构造函数,防止外部实例化
public static LazyMan lazyMan;
public static synchroized LazyMan getInstance(){ //加锁
if (lazyMan==null){
lazyMan = new LazyMan(); //用到该单例对象的时候再创建
}
return lazyMan;
}
}
双检锁(线程安全):【推荐使用】
- 实例化代码只用执行一次,后面再次访问时,判断
if (singleton == null),不为空则直接return实例化对象。 - 利用
volatile关键字保证了可见性,利用双重检查机制减少了同步带来的性能损耗。
public class Singleton {
private static volatile Singleton instance;
// 私有构造函数,防止外部实例化
private Singleton() {}
public static synchronized Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
饿汉式
(静态常量)【可用】
类一旦加载就创建一个单例,保证在调用getInstance方法之前单例已经存在,即没有延迟加载,这种饿汉式单例会造成空间浪费。
public class Hungry {
private Hungry(){}
private final static Hungry HUNGRY = new Hungry(); //在类内部就创建了一个静态对象,并且get方法返回该对象
public static Hungry getInstance(){
return HUNGRY;
}
}
//或者 静态代码块形式
public class Hungry {
static{
private final static Hungry HUNGRY = new Hungry();
}
private Hungry(){}
public static Hungry getInstance(){
return HUNGRY;
}
}
Hungry in1=Hungry.getInstance()
Hungry in2=Hungry.getInstance() //in1==in2
静态内部类
- (线程安全)单例:【推荐使用】
- 不仅线程安全,还实现了延迟加载
public class Inner {
private Inner(){}
//直到调用 getInstance() 方法之前,Inner 实例都不会被创建,实现了延迟初始化
public static Inner getInstance(){
return InnerClass.INNER;
}
private static class InnerClass{
private static final Inner INNER = new Inner(); //静态字段只会在类加载时被初始化一次,线程安全
}
}
枚举
- (线程安全)【推荐使用】不仅线程安全,还能防止反序列化导致重新创建新的对象
class SingletonEnum{
// 1、创建一个枚举
public enum CreateInstance{
// 枚举实例,底层变量定义是public static final,因此它在 JVM 中只会被初始化一次,并且是线程安全的
INSTANCE;
private SingletonEnum instance;
// 保证不能在类外部通过new构造器来构造对象
private CreateInstance() {
instance = new SingletonEnum();
System.out.println(Thread.currentThread().getName());
}
// 创建一个公共的方法,由实例调用返回单例类
public SingletonEnum getInstance() {
return instance;
}
}
public static void main(string[] args){
Singleton instance = CreateInstance.INSTANCE.getInstance();
singleton instance2= CreateInstance.INSTANCE.getInstance();
System.out.println(instance == instance2); //输出 true
}
}
原型模式
通过拷贝来创建新的对象,而不是通过实例化一个类,减少创建对象的成本,适用于创建对象成本高,需要大量相似对象的情况。
- Java 的 clone 仅是浅拷贝,默写场景需要 使用深拷贝避免共享数据的导致错乱
- 在 Spring 中,将 Bean 的作用范围设置为 prototype,这样每次从容器中获取 Bean 时,都会返回一个新的实例。
一个简单的原型模式实现例子如下
先创建一个原型类:
public class Prototype implements Cloneable { //一个原型类,只需要实现Cloneable接口,覆写clone方法
@Override
public Object clone() throws CloneNotSupportedException {
Prototype proto = (Prototype) super.clone(); //因为此处的重点是super.clone()这句话
return proto;
}
}
Prototype pro=new Prototype();
Prototype pro1=(Prototype)pro.clone(); //克隆 二者地址不同
//不管深浅,拷贝出来的对象的地址是不一样的,只是若对象里面有引用,那么深浅拷贝会不一样
@Data
public class Prototype implements Cloneable, Serializable {
private static final long serialVersionUID = 1L;
private String string;
private SerializableObject obj;
/* 浅拷贝 */
public Object clone() throws CloneNotSupportedException {
Prototype proto = (Prototype) super.clone();
return proto;
}
/* 深拷贝 */
public Object deepClone() throws IOException, ClassNotFoundException {
/* 写入当前对象的二进制流 */
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
/* 读出二进制流产生的新对象 */
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}
}
class SerializableObject implements Serializable {
private static final long serialVersionUID = 1L;
}
工厂模式
简单工厂
简单工厂模式通过传入的不同的参数来控制创建哪个具体产品。它的实现较为简单,但不够灵活,违反了开放封闭原则。
- 抽象产品接口: 定义了产品的规范,描述了产品的主要特性和功能
- 具体产品实现类: 实现或者继承抽象产品的子类
- 简单工厂: 提供了创建产品的方法,调用者通过该方法来获取产品。
// 产品接口
public interface Product {
void use();
}
// 具体产品A
public class ConcreteProductA implements Product {
@Override
public void use() {
System.out.println("Using ConcreteProductA");
}
}
// 具体产品B
public class ConcreteProductB implements Product {
@Override
public void use() {
System.out.println("Using ConcreteProductB");
}
}
// 简单工厂类
public class SimpleFactory {
public static Product createProduct(String type) {
switch (type) {
case "A":
return new ConcreteProductA();
case "B":
return new ConcreteProductB();
default:
throw new IllegalArgumentException("Unknown product type");
}
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
Product productA = SimpleFactory.createProduct("A");
productA.use(); // Output: Using ConcreteProductA
Product productB = SimpleFactory.createProduct("B");
productB.use(); // Output: Using ConcreteProductB
}
}
工厂方法
一个具体的工厂类负责生产一种产品
抽象工厂==>具体工厂
抽象产品==>具体产品(由具体工厂创建)
// 抽象产品
interface Product {
void use();
}
// 具体产品A
class ConcreteProductA implements Product {
public void use() {
System.out.println("Using ConcreteProductA");
}
}
// 具体产品B
class ConcreteProductB implements Product {
public void use() {
System.out.println("Using ConcreteProductB");
}
}
// 抽象工厂
interface Factory {
Product createProduct();
}
// 具体工厂A
class ConcreteFactoryA implements Factory {
public Product createProduct() {
return new ConcreteProductA();
}
}
// 具体工厂B
class ConcreteFactoryB implements Factory {
public Product createProduct() {
return new ConcreteProductB();
}
}
// 使用工厂方法创建产品
public class Client {
public static void main(String[] args) {
new ConcreteFactoryA().createProduct();
new ConcreteFactoryB().createProduct() ;
}
}
抽象工厂
- 是工厂方法的一种变体,创建一系列相关或相互依赖对象的接口,即生产一系列产品
- 给具体工厂类 添加一个工厂接口,使得工厂类可以多实现
// 抽象产品A
public interface ProductA {
void use();
}
// 具体产品A1
public class ConcreteProductA1 implements ProductA {
@Override
public void use() {
System.out.println("Using ConcreteProductA1");
}
}
// 具体产品A2
public class ConcreteProductA2 implements ProductA {
@Override
public void use() {
System.out.println("Using ConcreteProductA2");
}
}
// 抽象产品B
public interface ProductB {
void eat();
}
// 具体产品B1
public class ConcreteProductB1 implements ProductB {
@Override
public void eat() {
System.out.println("Eating ConcreteProductB1");
}
}
// 具体产品B2
public class ConcreteProductB2 implements ProductB {
@Override
public void eat() {
System.out.println("Eating ConcreteProductB2");
}
}
// 抽象工厂
public interface AbstractFactory {
ProductA createProductA();
ProductB createProductB();
}
// 具体工厂1
public class ConcreteFactory1 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA1();
}
@Override
public ProductB createProductB() {
return new ConcreteProductB1();
}
}
// 具体工厂2
public class ConcreteFactory2 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA2();
}
@Override
public ProductB createProductB() {
return new ConcreteProductB2();
}
}
// 使用抽象工厂创建产品
public class Client {
public static void main(String[] args) {
AbstractFactory factory1 = new ConcreteFactory1();
ProductA productA1 = factory1.createProductA();
ProductB productB1 = factory1.createProductB();
productA1.use();
productB1.eat();
AbstractFactory factory2 = new ConcreteFactory2();
ProductA productA2 = factory2.createProductA();
ProductB productB2 = factory2.createProductB();
productA2.use();
productB2.eat();
}
}
建造者模式
建造者模式使用相同的代码基础构建不同类型的对象,通过将对象构建过程分解为多个较小的步骤来实现此目的,如StringBuilder
两个主要组成部分:建造者和产品 建造者是负责构建产品的类,产品则是最终构建的对象
例如 hutool 内的 ExecutorBuilder 就提供了建造者模式创建线程池的方法
public ExecutorService buildTaskPool() {
return ExecutorBuilder.create()
.setCorePoolSize(10)
.setMaxPoolSize(20)
.setWorkQueue(new LinkedBlockingQueue<>(100))
.setKeepAliveTime(3L, TimeUnit.SECONDS)
.setThreadFactory(new ThreadFactoryBuilder().setNamePrefix("task-pool-").build())
.build();
}
public class Product { //最终构建的对象,即产品
private String partA;
private String partB;
private String partC;
public void setPartA(String partA) {
this.partA = partA;
}
public void setPartB(String partB) {
this.partB = partB;
}
public void setPartC(String partC) {
this.partC = partC;
}
// other product-related methods
}
public interface Builder { //Builder接口或抽象类,定义了构建过程的关键步骤
void buildPartA();
void buildPartB();
void buildPartC();
Product getResult();
}
public class ConcreteBuilder implements Builder { //实现了Builder接口中定义的方法,以构建具体的Product对象
private Product product = new Product();
public void buildPartA() {
product.setPartA("Part A");
}
public void buildPartB() {
product.setPartB("Part B");
}
public void buildPartC() {
product.setPartC("Part C");
}
public Product getResult() {
return product;
}
}
public class Director { //指导类,它负责使用Builder对象来构建最终的Product对象
private Builder builder;
public Director(Builder builder) { //实现依赖倒置原则,依赖于抽象
this.builder = builder;
}
public void construct() { //确保Product对象按照指定的顺序创建
builder.buildPartA();
builder.buildPartB();
builder.buildPartC();
}
}
Builder builder = new ConcreteBuilder(); //创建建造者
Director director = new Director(builder); //创建指导
director.construct();
Product product = builder.getResult();
//这将构建一个Product对象,并将其存储在product变量中。
设计模式之创建型模式详解
4405

被折叠的 条评论
为什么被折叠?



