深入理解设计模式:工厂模式、单例模式
设计模式是软件开发中解决常见问题的可复用方案。本文将详细介绍两种种重要的创建型设计模式:工厂模式、单例模式,并提供Java实现示例。
一、工厂模式
工厂模式是一种创建对象的设计模式,它提供了一种创建对象的最佳方式,而无需向客户端暴露创建逻辑。
1.1 简单工厂模式
简单工厂模式由一个工厂类负责创建所有产品。
java
// 产品接口
interface Product {
void operation();
}
// 具体产品A
class ConcreteProductA implements Product {
@Override
public void operation() {
System.out.println("ConcreteProductA operation");
}
}
// 具体产品B
class ConcreteProductB implements Product {
@Override
public 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 工厂方法模式
工厂方法模式将实际创建对象的责任委托给子类。
java
// 产品接口
interface Product {
void operation();
}
// 具体产品A
class ConcreteProductA implements Product {
@Override
public void operation() {
System.out.println("ConcreteProductA operation");
}
}
// 具体产品B
class ConcreteProductB implements Product {
@Override
public void operation() {
System.out.println("ConcreteProductB operation");
}
}
// 工厂接口
interface Factory {
Product createProduct();
}
// 具体工厂A
class ConcreteFactoryA implements Factory {
@Override
public Product createProduct() {
return new ConcreteProductA();
}
}
// 具体工厂B
class ConcreteFactoryB implements Factory {
@Override
public 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 抽象工厂模式
抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
java
// 产品A接口
interface ProductA {
void operationA();
}
// 产品B接口
interface ProductB {
void operationB();
}
// 具体产品A1
class ConcreteProductA1 implements ProductA {
@Override
public void operationA() {
System.out.println("ConcreteProductA1 operationA");
}
}
// 具体产品A2
class ConcreteProductA2 implements ProductA {
@Override
public void operationA() {
System.out.println("ConcreteProductA2 operationA");
}
}
// 具体产品B1
class ConcreteProductB1 implements ProductB {
@Override
public void operationB() {
System.out.println("ConcreteProductB1 operationB");
}
}
// 具体产品B2
class ConcreteProductB2 implements ProductB {
@Override
public void operationB() {
System.out.println("ConcreteProductB2 operationB");
}
}
// 抽象工厂接口
interface AbstractFactory {
ProductA createProductA();
ProductB createProductB();
}
// 具体工厂1
class ConcreteFactory1 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA1();
}
@Override
public ProductB createProductB() {
return new ConcreteProductB1();
}
}
// 具体工厂2
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.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 饿汉式单例
java
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 懒汉式单例(线程安全)
java
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 枚举实现单例
java
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 静态内部类实现单例
java
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 适用场景
- 需要频繁创建和销毁的对象
- 创建对象时耗时过多或耗费资源过多的对象
- 工具类对象
- 频繁访问数据库或文件的对象
总结
本文详细介绍了两种种常用的创建型设计模式:工厂模式、单例模式和建造者模式。它们各自有不同的应用场景:
- 工厂模式:当需要将对象的创建与使用分离,或者需要创建一系列相关对象时使用。
- 单例模式:当系统中需要保证一个类只有一个实例,并提供全局访问点时使用。
这些设计模式都是面向对象设计的重要工具,理解并正确应用它们可以帮助我们编写出更加灵活、可维护的代码。