1.单例设计模式(20260319)
单例模式确保一个类只有一个实例,并提供全局访问点。核心原理:
- 私有化构造方法(禁止外部创建实例)
- 静态私有成员(持有唯一实例)
- 静态公有方法(提供全局访问入口)
(1)饿汉式
java
public class EagerSingleton {
// 类加载时立即初始化(线程安全由JVM保证)
private static final EagerSingleton INSTANCE = new EagerSingleton();
private EagerSingleton() {} // 私有构造
public static EagerSingleton getInstance() {
return INSTANCE;
}
}
-
优点:实现简单,线程安全
-
缺点:非懒加载,可能造成资源浪费
(2)饱汉式
java
public class LazySingleton {
private static LazySingleton instance;
private LazySingleton() {}
// 方法同步保证线程安全(性能瓶颈)
public static synchronized LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
-
优点:懒加载
-
缺点:同步方法性能差(每次调用都加锁)
(3)双重检查锁(DCL)
java
public class DCLSingleton {
// volatile禁止指令重排序(防止返回未初始化的对象)
private volatile static DCLSingleton instance;
private DCLSingleton() {}
public static DCLSingleton getInstance() {
if (instance == null) { // 第一次检查(避免不必要的锁)
synchronized (DCLSingleton.class) {
if (instance == null) { // 第二次检查(确保唯一性)
instance = new DCLSingleton();
}
}
}
return instance;
}
}
双重检查的原理:避免不必要的加锁,单例一旦初始化完成,后续 99.99% 的调用都不需要进入 synchronized
volatile:对象创建不是原子操作,在 JVM 层面大致分为三步:
- 分配内存
- 调用构造方法,初始化对象
- 将引用指向分配的内存
2和3可能会互换,返回未初始化完成的对象
禁止指令重排序,保证可见性
(4)静态内部类(Holder)
java
public class HolderSingleton {
private HolderSingleton() {}
// 静态内部类在首次使用时加载
private static class Holder {
static final HolderSingleton INSTANCE = new HolderSingleton();
}
public static HolderSingleton getInstance() {
return Holder.INSTANCE; // 触发类加载(线程安全由JVM保证)
}
}
静态内部类单例利用了 JVM 类加载机制:内部类在首次被主动使用时才会初始化,而类初始化过程由 JVM 保证线程安全和可见性,因此无需显式同步或 volatile,就能实现高性能的懒加载单例。
2.工厂设计模式
核心本质是:
- 实例化对象不使用new,用工厂方法创建对象
- 使用工厂统一管理对象的创建,将调用者跟实现类解耦
(1)简单工厂模式
建立一个工厂类,对实现了同一接口的一些类进行实例的创建。

java
public interface Phone {
public void call();
}
public class IPhone implements Phone{
@Override
public void call() {
System.out.println("用苹果手机打电话!");
}
}
public class MPhone implements Phone{
@Override
public void call() {
System.out.println("用小米手机打电话!");
}
}
public class PhoneFactory {
public Phone create(String type){
if (type.equals("IPhone")){
return new IPhone();
}else if (type.equals("MPhone")){
return new MPhone();
}else
return null;
}
}
(2)工厂方法模式
-
工厂方法模式,创建一个工厂接口和创建多个工厂实现类,一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。有利于代码的维护和扩展。

java
public interface PhoneFactory {
public Phone create();
}
public class MPhoneFactory implements PhoneFactory{
@Override
public Phone create() {
return new MPhone();
}
}
public class IPhoneFactory implements PhoneFactory{
@Override
public Phone create() {
return new IPhone();
}
}
(3)抽象工厂模式
围绕一个超级工厂创建其他工厂,每个工厂可以生产不同类型的产品

java
public interface Factory {
public Phone createPhone();
public Book createBook();
}
public class AppleFactory implements Factory{
@Override
public Phone createPhone() {
return new IPhone();
}
@Override
public Book createBook() {
return new MacBook();
}
}
public class XiaoMiFactory implements Factory{
@Override
public Phone createPhone() {
return new MPhone();
}
@Override
public Book createBook() {
return new MiBook();
}
}
3.模版方法模式
在一个抽象类公开定义了执行它的方法的模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。

java
// 抽象类,表示豆浆 SoyaMilk.java
public abstract class SoyaMilk {
// 模板方法:可以做成final,不让子类去覆盖
final void make() {
select();
addCondiment();
soak();
beat();
}
//选材料
void select() { System.out.println("第一步:选择新鲜的豆子"); }
//添加不同的配料:抽象方法,由子类具体实现
abstract void addCondiment();
//浸泡
void soak() { System.out.println("第三步:豆子和配料开始浸泡3H"); }
//榨汁
void beat() { System.out.println("第四步:豆子和配料放入豆浆机榨汁"); }
}
// RedBeanSoyaMilk.java
public class ReadBeanSoyaMilk extends SoyaMilk {
@Override
void addCondiment() {
System.out.println("第二步:加入上好的红豆");
}
}
// PeanutSoyMilk.java
public class PeanutSoyaMilk extends SoyaMilk {
@Override
void addCondiment() {
System.out.println("第二步:加入上好的花生");
}
}
// Client.java
public class Client {
public static void main(String[] args) {
System.out.println("=======制作红豆豆浆=======");
SoyaMilk redBeanSoyaMilk = new ReadBeanSoyaMilk();
redBeanSoyaMilk.make();
System.out.println("=======制作花生豆浆=======");
SoyaMilk peanutSoyaMilk = new PeanutSoyaMilk();
peanutSoyaMilk.make();
}
}
) {
System.out.println("=制作红豆豆浆=");
SoyaMilk redBeanSoyaMilk = new ReadBeanSoyaMilk();
redBeanSoyaMilk.make();
System.out.println("=======制作花生豆浆=======");
SoyaMilk peanutSoyaMilk = new PeanutSoyaMilk();
peanutSoyaMilk.make();
}
}