当前位置: 首页 > news >正文

深入理解设计模式:工厂模式、单例模式

深入理解设计模式:工厂模式、单例模式

设计模式是软件开发中解决常见问题的可复用方案。本文将详细介绍两种种重要的创建型设计模式:工厂模式、单例模式,并提供Java实现示例。

一、工厂模式

工厂模式是一种创建对象的设计模式,它提供了一种创建对象的最佳方式,而无需向客户端暴露创建逻辑。

1.1 简单工厂模式

简单工厂模式由一个工厂类负责创建所有产品。

// 产品接口
interface Product {void operation();
}// 具体产品A
class ConcreteProductA implements Product {@Overridepublic void operation() {System.out.println("ConcreteProductA operation");}
}// 具体产品B
class ConcreteProductB implements Product {@Overridepublic void operation() {System.out.println("ConcreteProductB operation");}
}// 简单工厂
class SimpleFactory {public static Product createProduct(String type) {if ("A".equals(type)) {return new ConcreteProductA();} else if ("B".equals(type)) {return new ConcreteProductB();}throw new IllegalArgumentException("Unknown product type");}
}// 客户端代码
public class Client {public static void main(String[] args) {Product productA = SimpleFactory.createProduct("A");productA.operation();Product productB = SimpleFactory.createProduct("B");productB.operation();}
}

1.2 工厂方法模式

工厂方法模式将实际创建对象的责任委托给子类。

// 产品接口
interface Product {void operation();
}// 具体产品A
class ConcreteProductA implements Product {@Overridepublic void operation() {System.out.println("ConcreteProductA operation");}
}// 具体产品B
class ConcreteProductB implements Product {@Overridepublic void operation() {System.out.println("ConcreteProductB operation");}
}// 工厂接口
interface Factory {Product createProduct();
}// 具体工厂A
class ConcreteFactoryA implements Factory {@Overridepublic Product createProduct() {return new ConcreteProductA();}
}// 具体工厂B
class ConcreteFactoryB implements Factory {@Overridepublic Product createProduct() {return new ConcreteProductB();}
}// 客户端代码
public class Client {public static void main(String[] args) {Factory factoryA = new ConcreteFactoryA();Product productA = factoryA.createProduct();productA.operation();Factory factoryB = new ConcreteFactoryB();Product productB = factoryB.createProduct();productB.operation();}
}

1.3 抽象工厂模式

抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

// 产品A接口
interface ProductA {void operationA();
}// 产品B接口
interface ProductB {void operationB();
}// 具体产品A1
class ConcreteProductA1 implements ProductA {@Overridepublic void operationA() {System.out.println("ConcreteProductA1 operationA");}
}// 具体产品A2
class ConcreteProductA2 implements ProductA {@Overridepublic void operationA() {System.out.println("ConcreteProductA2 operationA");}
}// 具体产品B1
class ConcreteProductB1 implements ProductB {@Overridepublic void operationB() {System.out.println("ConcreteProductB1 operationB");}
}// 具体产品B2
class ConcreteProductB2 implements ProductB {@Overridepublic void operationB() {System.out.println("ConcreteProductB2 operationB");}
}// 抽象工厂接口
interface AbstractFactory {ProductA createProductA();ProductB createProductB();
}// 具体工厂1
class ConcreteFactory1 implements AbstractFactory {@Overridepublic ProductA createProductA() {return new ConcreteProductA1();}@Overridepublic ProductB createProductB() {return new ConcreteProductB1();}
}// 具体工厂2
class ConcreteFactory2 implements AbstractFactory {@Overridepublic ProductA createProductA() {return new ConcreteProductA2();}@Overridepublic 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.operationA();productB1.operationB();AbstractFactory factory2 = new ConcreteFactory2();ProductA productA2 = factory2.createProductA();ProductB productB2 = factory2.createProductB();productA2.operationA();productB2.operationB();}
}

1.4 工厂模式的优缺点

优点:

  • 封装了对象的创建过程,客户端无需了解具体产品类
  • 可以轻松添加新产品而不影响现有代码
  • 遵循开闭原则

缺点:

  • 引入了额外的类和接口,增加了系统复杂度
  • 在某些情况下可能会增加系统的抽象程度和理解难度

1.5 适用场景

  • 当一个类不知道它所需要创建的对象的类时
  • 当一个类希望由子类来指定它所创建的对象时
  • 当创建对象的过程涉及到复杂的业务逻辑时

二、单例模式

单例模式确保一个类只有一个实例,并提供一个全局访问点。

2.1 饿汉式单例

public class EagerSingleton {// 在类加载时就创建实例private static final EagerSingleton INSTANCE = new EagerSingleton();// 私有构造函数,防止外部实例化private EagerSingleton() {// 防止通过反射创建多个实例if (INSTANCE != null) {throw new IllegalStateException("Singleton already initialized");}}// 提供全局访问点public static EagerSingleton getInstance() {return INSTANCE;}// 示例方法public void doSomething() {System.out.println("Singleton is doing something");}
}

2.2 懒汉式单例(线程安全)

public class LazySingleton {// 初始不创建实例private static volatile LazySingleton instance;// 私有构造函数private LazySingleton() {// 防止通过反射创建多个实例if (instance != null) {throw new IllegalStateException("Singleton already initialized");}}// 提供全局访问点,使用双重检查锁定public static LazySingleton getInstance() {if (instance == null) {synchronized (LazySingleton.class) {if (instance == null) {instance = new LazySingleton();}}}return instance;}// 示例方法public void doSomething() {System.out.println("Singleton is doing something");}
}

2.3 枚举实现单例

public enum EnumSingleton {INSTANCE;// 示例方法public void doSomething() {System.out.println("Enum Singleton is doing something");}
}// 使用方式
public class Client {public static void main(String[] args) {EnumSingleton.INSTANCE.doSomething();}
}

2.4 静态内部类实现单例

public class StaticInnerSingleton {// 私有构造函数private StaticInnerSingleton() {}// 静态内部类持有单例实例private static class SingletonHolder {private static final StaticInnerSingleton INSTANCE = new StaticInnerSingleton();}// 提供全局访问点public static StaticInnerSingleton getInstance() {return SingletonHolder.INSTANCE;}// 示例方法public void doSomething() {System.out.println("Static inner class Singleton is doing something");}
}

2.5 单例模式的优缺点

优点:

  • 保证一个类只有一个实例,减少内存开销
  • 提供全局访问点,便于全局控制
  • 实例只创建一次,避免多次实例化的性能开销

缺点:

  • 不适用于变化频繁的对象
  • 单例模式的扩展有一定难度
  • 单例可能导致单一职责原则的违反

2.6 适用场景

  • 需要频繁创建和销毁的对象
  • 创建对象时耗时过多或耗费资源过多的对象
  • 工具类对象
  • 频繁访问数据库或文件的对象

总结

本文详细介绍了两种种常用的创建型设计模式:工厂模式、单例模式和建造者模式。它们各自有不同的应用场景:

  • 工厂模式:当需要将对象的创建与使用分离,或者需要创建一系列相关对象时使用。
  • 单例模式:当系统中需要保证一个类只有一个实例,并提供全局访问点时使用。

这些设计模式都是面向对象设计的重要工具,理解并正确应用它们可以帮助我们编写出更加灵活、可维护的代码。

http://www.xdnf.cn/news/622027.html

相关文章:

  • QTabWidget垂直TabBar的图标和文本水平显示
  • Java 连接并操作 Redis 万字详解:从 Jedis 直连到 RedisTemplate 封装,5 种方式全解析
  • 第十七次CCF-CSP算法(含C++源码)
  • C++八股 —— 手撕定时器
  • QT之INI、JSON、XML处理
  • 深入理解Redis线程模型
  • Docker 镜像调试最佳实践
  • HarmonyOS优化应用内存占用问题性能优化四
  • ihoneyBakFileScan (修改针对.net备份文件扫描)
  • 配置文件,xml,json,yaml,我该选哪个?
  • SpringBoot多环境配置文件切换
  • 算法笔记·数学·最大公约数
  • 基于ZYNQ的LWIP网络TCP/IP调试
  • Spring AI 1.0.0 中文文档上线
  • 在WPF中添加动画背景
  • 道德经总结
  • Spring MVC深度解析:控制器与视图解析及RESTful API设计最佳实践
  • 1267: 【入门】鲜花方阵
  • 【PhysUnits】10 减一操作(sub1.rs)
  • Python学习心得:代码森林的冒险
  • SYN Flood攻击:原理、危害与防御指南
  • PostGIS实现栅格数据转二进制应用实践【ST_AsBinary】
  • 【esp32 WIFI连接】-STA模式
  • rce命令执行原理及靶场实战(详细)
  • Vue项目前后端交互大量数据的-之-前端优化方案
  • 前端流行框架Vue3教程:25. 组件保持存活
  • 湖北理元理律师事务所债务优化方案解析:如何科学规划还款保障生活质量
  • 0304考试通过-逻辑回归实战-机器学习-人工智能
  • Symbol、Set 与 Map:新数据结构探秘
  • uniapp-商城-66-shop(2-品牌信息显示,数据库读取的异步操作 放到vuex actions)