Java 原型模式、建造者模式、单例模式

原型模式、建造者模式

原型模式

原型模式(Prototype Pattern)是一种创建型设计模式,它允许你通过复制现有对象来创建新对象,而不是通过实例化类。这种模式在需要大量相似对象时非常有用,因为它可以减少创建对象的开销。

原型模式的應用場景

  1. 性能和资源管理:当创建对象的代价较大时,可以使用原型模式减少创建对象的开销。
  2. 避免构造函数的复杂性:如果对象的创建过程非常复杂,可以通过克隆已有对象来简化创建过程。
  3. 隔离复杂对象的创建:在某些情况下,直接使用构造函数可能会使代码变得复杂,而通过克隆可以简化代码。
  4. 缓存实例:在某些场景下,可以预先创建一些对象并缓存起来,需要时直接克隆这些对象。

Java 原型模式的代碼實例

以下是一个简单的Java示例,展示了如何使用原型模式:

java 复制代码
// 定义一个抽象的原型接口
interface Prototype {
    Prototype clone();
}

// 实现具体的原型类
class ConcretePrototype implements Prototype {
    private String field;

    public ConcretePrototype(String field) {
        this.field = field;
    }

    @Override
    public Prototype clone() {
        return new ConcretePrototype(this.field);
    }

    @Override
    public String toString() {
        return "ConcretePrototype{" +
                "field='" + field + '\'' +
                '}';
    }
}

// 客户端代码
public class PrototypePatternDemo {
    public static void main(String[] args) {
        // 创建一个原始对象
        ConcretePrototype original = new ConcretePrototype("Original");
        System.out.println("Original: " + original);

        // 克隆原始对象
        ConcretePrototype clone = (ConcretePrototype) original.clone();
        System.out.println("Clone: " + clone);
    }
}

在这个示例中:

  1. Prototype接口定义了一个clone方法,用于克隆对象。
  2. ConcretePrototype类实现了Prototype接口,并提供了clone方法的具体实现。
  3. 在客户端代码中,我们创建了一个原始对象,并通过调用clone方法创建了它的副本。

这样,通过原型模式,我们可以方便地创建对象的副本,而不需要每次都通过构造函数来创建新的对象。


建造者模式

建造者模式(Builder Pattern)是一种创建型设计模式,它允许你通过一步一步地构建复杂对象。这种模式特别适用于需要创建具有多个可选参数的对象时,可以避免构造函数参数过多的问题。

建造者模式的應用場景

  1. 复杂对象的创建:当一个对象有很多属性,并且这些属性可能有不同的组合时,使用建造者模式可以简化对象的创建过程。
  2. 避免构造函数参数过多:如果一个类的构造函数有多个参数,使用建造者模式可以使代码更加清晰和易于维护。
  3. 不可变对象:在创建不可变对象时,建造者模式可以帮助确保对象在构建过程中不会被修改。
  4. 流式接口:建造者模式通常提供流式接口,使代码更具可读性。

Java 建造者模式的代碼實例

以下是一个简单的Java示例,展示了如何使用建造者模式:

java 复制代码
// 产品类
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; }

    @Override
    public String toString() {
        return "Product{" +
                "partA='" + partA + '\'' +
                ", partB='" + partB + '\'' +
                ", partC='" + partC + '\'' +
                '}';
    }
}

// 抽象建造者类
abstract class Builder {
    protected Product product = new Product();

    public abstract void buildPartA();
    public abstract void buildPartB();
    public abstract void buildPartC();

    public Product getResult() {
        return product;
    }
}

// 具体建造者类
class ConcreteBuilder extends Builder {
    @Override
    public void buildPartA() {
        product.setPartA("Part A");
    }

    @Override
    public void buildPartB() {
        product.setPartB("Part B");
    }

    @Override
    public void buildPartC() {
        product.setPartC("Part C");
    }
}

// 指挥者类
class Director {
    private Builder builder;

    public Director(Builder builder) {
        this.builder = builder;
    }

    public void construct() {
        builder.buildPartA();
        builder.buildPartB();
        builder.buildPartC();
    }
}

// 客户端代码
public class BuilderPatternDemo {
    public static void main(String[] args) {
        Builder builder = new ConcreteBuilder();
        Director director = new Director(builder);
        director.construct();
        Product product = builder.getResult();
        System.out.println(product);
    }
}

在这个示例中:

  1. Product类是我们要构建的复杂对象。
  2. Builder是一个抽象类,定义了构建不同部分的方法。
  3. ConcreteBuilder是具体的建造者类,实现了Builder类的方法。
  4. Director类负责控制建造过程,按照一定的顺序调用建造者的方法。
  5. 在客户端代码中,我们创建了一个具体的建造者实例和一个指挥者实例,然后通过指挥者来构建产品。

这样,通过建造者模式,我们可以灵活地构建复杂对象,同时保持代码的清晰和可维护性。


单例模式

单例模式(Singleton Pattern)是Java设计模式中最简单的一种,它确保一个类在整个应用程序运行期间只有一个实例,并提供一个全局访问点。这种模式在需要控制资源唯一性或对共享资源进行管理时非常有用。

单例模式是一种创建型设计模式,其目的是确保某个类在系统中只有一个实例存在,并提供一个全局访问该实例的方法。通过这种方式,可以有效地控制资源的使用,避免不必要的实例化开销。单例模式适用于以下场景:

  • 需要控制资源的唯一性,如数据库连接池、配置文件管理器等。
  • 需要对共享资源进行集中管理,如线程池、日志记录器等。

二、单例模式的实现方式

单例模式有多种实现方法,主要包括懒汉式、饿汉式、双重检查锁和静态内部类。每种方法都有其优缺点,适用于不同的场景。

1. 懒汉式(Lazy Initialization)

懒汉式单例模式只有在第一次使用时才会创建实例。这种方式适用于实例化开销较大的对象,且该对象在程序运行初期不一定会被使用。

代码示例:

java 复制代码
public class LazySingleton {
    private static LazySingleton instance;

    private LazySingleton() {
        // 私有化构造函数
    }

    public static synchronized LazySingleton getInstance() {
        if (instance == null) {
            instance = new LazySingleton();
        }
        return instance;
    }
}

适用场景:

  • 实例化开销较大的对象。
  • 程序启动时不需要立即加载的对象。

优缺点:

  • 优点:延迟加载,减少内存开销。
  • 缺点:多线程环境下性能较差,因为每次获取实例时都需要进行同步。
2. 饿汉式(Eager Initialization)

饿汉式单例模式在类加载时就创建实例,适用于程序运行过程中必然会使用到的实例。

代码示例:

java 复制代码
public class EagerSingleton {
    private static final EagerSingleton instance = new EagerSingleton();

    private EagerSingleton() {
        // 私有化构造函数
    }

    public static EagerSingleton getInstance() {
        return instance;
    }
}

适用场景:

  • 启动时需要立即加载并长期使用的对象。

优缺点:

  • 优点:实现简单,线程安全。
  • 缺点:由于实例是在类加载时创建的,可能会导致内存浪费,尤其是在实例一直没有被使用的情况下。
3. 双重检查锁(Double-Check Locking)

双重检查锁机制在多线程环境下使用,确保实例的唯一性和线程安全性。

代码示例:

java 复制代码
public class DoubleCheckedLockingSingleton {
    private static volatile DoubleCheckedLockingSingleton instance;

    private DoubleCheckedLockingSingleton() {
        // 私有化构造函数
    }

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

适用场景:

  • 需要延迟加载单例对象且需要确保多线程安全的场景。

优缺点:

  • 优点:线程安全,避免了不必要的同步开销。
  • 缺点:实现复杂,可能会增加代码的可维护性难度。
4. 静态内部类(Static Inner Class)

利用Java的类加载机制,静态内部类实现单例模式既实现了延迟加载,又保证了线程安全。

代码示例:

java 复制代码
public class StaticInnerClassSingleton {
    private StaticInnerClassSingleton() {
        // 私有化构造函数
    }

    private static class SingletonHelper {
        private static final StaticInnerClassSingleton INSTANCE = new StaticInnerClassSingleton();
    }

    public static StaticInnerClassSingleton getInstance() {
        return SingletonHelper.INSTANCE;
    }
}

适用场景:

  • 需要延迟加载但不希望增加代码复杂度的场景。

优缺点:

  • 优点:延迟加载,线程安全,且实现简单。
  • 缺点:无法在实例化时传递参数。

三、单例模式的应用场景

单例模式在实际应用中非常广泛,特别是在需要控制资源唯一性的场合。以下是几个典型的应用场景:

1. 配置管理器

在一个电商系统中,各种配置如数据库连接、API密钥等通常都是全局的且不会频繁更改。这些配置数据可以封装在一个配置管理器类中,并使用单例模式来确保只有一个实例来管理所有配置。

代码示例:

java 复制代码
public class ConfigurationManager {
    private static ConfigurationManager instance;
    private Properties properties;

    private ConfigurationManager() {
        properties = new Properties();
        // 加载配置文件
        try (InputStream input = new FileInputStream("config.properties")) {
            properties.load(input);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static synchronized ConfigurationManager getInstance() {
        if (instance == null) {
            instance = new ConfigurationManager();
        }
        return instance;
    }

    // 获取配置信息的方法
    public String getProperty(String key) {
        return properties.getProperty(key);
    }
}

在这个例子中,ConfigurationManager类使用了懒汉式单例模式,确保配置文件只被加载一次,并且在应用程序的任何地方都可以通过ConfigurationManager.getInstance()来获取配置实例。

2. 数据库连接池

数据库连接池是用来管理和复用数据库连接的对象。为了避免频繁创建和销毁连接带来的性能开销,可以使用单例模式来管理连接池。

代码示例:

java 复制代码
public class DatabaseConnectionPool {
    private static DatabaseConnectionPool instance;
    private List<Connection> connections;

    private DatabaseConnectionPool() {
        connections = new ArrayList<>();
        // 初始化连接池中的连接
        for (int i = 0; i < 10; i++) {
            connections.add(createConnection());
        }
    }

    public static synchronized DatabaseConnectionPool getInstance() {
        if (instance == null) {
            instance = new DatabaseConnectionPool();
        }
        return instance;
    }

    // 获取连接的方法
    public Connection getConnection() {
        if (connections.isEmpty()) {
            throw new SQLException("No available connections");
        } else {
            return connections.remove(connections.size() - 1);
        }
    }

    // 释放连接的方法
    public void releaseConnection(Connection connection) {
        connections.add(connection);
    }
}

在这个例子中,DatabaseConnectionPool类使用了懒汉式单例模式,确保连接池只被初始化一次,并且在应用程序的任何地方都可以通过DatabaseConnectionPool.getInstance()来获取连接池实例。

3. 日志记录器

在大型应用中,日志记录通常由一个集中的日志记录器负责。通过单例模式,可以确保日志记录器的唯一性,避免多个实例导致的日志混乱。

代码示例:

java 复制代码
public class Logger {
    private static Logger instance;
    private static List<String> logEntries;

    private Logger() { }

    public static synchronized Logger getInstance() {
        if (instance == null) {
            instance = new Logger();
            logEntries = new ArrayList<>();
        }
        return instance;
    }

    // 记录日志的方法
    public void log(String message) {
        logEntries.add(message);
        System.out.println(message); // 输出到控制台,也可以输出到文件或其他介质
    }
}

在这个例子中,Logger类使用了懒汉式单例模式,确保日志记录器只被初始化一次,并且在应用程序的任何地方都可以通过Logger.getInstance()来获取日志记录器实例。


END

相关推荐
Yang-Never6 分钟前
Shader -> RadialGradient圆心渐变着色器详解
android·java·kotlin·android studio
master-dragon38 分钟前
Spring bean的生命周期和扩展
java·spring
java1234_小锋40 分钟前
Redis有哪些常用应用场景?
java·数据库·redis
3D小将1 小时前
3D 建模的未来发展呈现出以下几个趋势
3d·建造者模式
beiback1 小时前
下载导出Tomcat上的excle文档,浏览器上显示下载
java·tomcat
小学鸡!1 小时前
spring boot发送邮箱,java实现邮箱发送(邮件带附件)3中方式【保姆级教程一,代码直接用】
java·spring boot
cloud___fly1 小时前
Java常用设计模式
java·设计模式
yasinzhang2 小时前
记录IDEA与maven兼容版本
java·maven·intellij-idea
loveLifeLoveCoding2 小时前
springboot 默认的 mysql 驱动版本
java·spring boot·mysql
多多*2 小时前
后端技术选型 sa-token校验学习 下 结合项目学习 后端鉴权
java·开发语言·前端·学习·算法·bootstrap·intellij-idea