单例模式是设计模式中的一种,属于创建型模式。在软件工程中,单例模式确保一个类只有一个实例,并提供一个全局访问点。这种模式常用于那些需要频繁实例化然后引用,且创建新实例的开销较大的类,例如数据库连接池、缓存管理等。
意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
主要解决:一个全局使用的类频繁地创建与销毁所造成的资源浪费问题。
何时使用:当您想控制实例数目,节省系统资源的时候。
如何解决:判断系统是否已经有这个单例,如果有则返回,如果没有则创建。
关键代码:构造函数是私有的。
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
这种方式在多线程环境下不能保证单例,因为多个线程可能同时进入if条件判断内部,导致创建多个实例。
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
通过在getInstance方法上加synchronized关键字使其变为同步方法,解决了多线程环境下的安全性问题,但每次获取实例都要进行同步,性能损耗较大。
public class Singleton {
private volatile static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
双重检查锁定机制,首先判断实例是否存在,若不存在才进行同步处理,这样既保证了线程安全,又避免了每次都进行同步带来的性能损耗。
public class Singleton {
private Singleton() {}
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
静态内部类的方式在类加载时就完成了初始化,既保证了线程安全,也避免了同步带来的性能影响,同时也能保证单例对象的唯一性。
public enum Singleton {
INSTANCE;
public void whateverMethod() {
// ...
}
}
枚举类型的单例模式不仅能防止反射和反序列化的攻击,而且写法简单,易于理解,是实现单例的最佳选择。
以上就是Java单例模式的详细解读,实际开发过程中应根据具体场景选择合适的实现方式。
工厂模式是面向对象设计模式中的一种,主要用来解决对象创建的问题,封装了对象的创建过程,使客户端不需要知道具体的实现类就能创建所需的对象。根据抽象程度的不同,工厂模式分为简单工厂模式、工厂方法模式和抽象工厂模式。
意图:提供一个用于创建对象的接口,让子类决定实例化哪一个类。
结构:由一个工厂类负责创建不同类的产品对象。
// 简单工厂角色
public class ShapeFactory {
public Shape getShape(String type) {
if ("CIRCLE".equals(type)) {
return new Circle();
} else if ("RECTANGLE".equals(type)) {
return new Rectangle();
} else if ("SQUARE".equals(type)) {
return new Square();
} else {
throw new IllegalArgumentException("Invalid shape type");
}
}
}
// 抽象产品角色
abstract class Shape {
abstract void draw();
}
// 具体产品角色
class Circle extends Shape {
@Override
void draw() {
System.out.println("Drawing a circle...");
}
}
// 其他具体产品类...
意图:定义一个用于创建对象的接口,但让子类决定实例化哪个类。工厂方法使一个类的实例化延迟到其子类。
结构:定义一个创建产品对象的接口,让子类决定生产什么产品。
// 抽象工厂角色
interface ShapeFactory {
Shape createShape();
}
// 具体工厂角色
class CircleFactory implements ShapeFactory {
@Override
Shape createShape() {
return new Circle();
}
}
// 其他具体工厂类...
// 抽象产品角色
abstract class Shape {
abstract void draw();
}
// 具体产品角色
class Circle extends Shape {
@Override
void draw() {
System.out.println("Drawing a circle...");
}
}
// 其他具体产品类...
意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们的具体类。
结构:提供一个接口,用于创建相关或相互依赖对象家族的一系列对象,而无需指定具体类。
// 抽象工厂角色
interface ColorFactory {
Color getColor();
}
interface ShapeFactory {
Shape getShape();
}
// 具体工厂角色
class RedColorFactory implements ColorFactory {
@Override
Color getColor() {
return new RedColor();
}
}
class CircleShapeFactory implements ShapeFactory {
@Override
Shape getShape() {
return new Circle();
}
}
// 抽象产品角色
interface Color {
void fill();
}
interface Shape {
void draw();
}
// 具体产品角色
class RedColor implements Color {
@Override
void fill() {
System.out.println("Filling with red color...");
}
}
class Circle implements Shape {
@Override
void draw() {
System.out.println("Drawing a circle...");
}
}
// 其他具体产品类...
优点
缺点
通过上述介绍,您应该对Java中的工厂设计模式有了较为深入的理解。在实际开发中,可以根据需求选择合适的工厂模式来组织代码,提高程序的灵活性和可维护性。
代理设计模式(Proxy Design Pattern)是软件设计中常用的行为型设计模式之一,它为其他对象提供一个代理以控制对这个对象的访问。在Java编程中,代理模式的主要目的是为了在不改变原始目标类代码的基础上,通过引入一个额外的代理类来扩展或增强原有对象的功能。
代理模式定义如下:
代理模式:给某个对象提供一个代理,并由代理对象控制对原对象的引用。代理模式能够在客户端与目标对象之间增加一层间接层,从而实现对目标对象功能的增强、控制或者过滤。
在Java中,代理主要分为两种类型:
静态代理是在编译期间就已经确定代理类,代理类和被代理类的关系在代码中硬编码。
public interface Subject {
void request();
}
public class RealSubject implements Subject {
@Override
public void request() {
// 真实对象的实际业务逻辑
}
}
public class ProxySubject implements Subject {
private RealSubject realSubject;
public ProxySubject(RealSubject realSubject) {
this.realSubject = realSubject;
}
@Override
public void request() {
beforeRequest(); // 在调用实际方法前的操作
realSubject.request();
afterRequest(); // 在调用实际方法后的操作
}
private void beforeRequest() {
// 添加前置逻辑,比如权限校验
}
private void afterRequest() {
// 添加后置逻辑,比如日志记录
}
}
Java提供了动态生成代理类的技术,主要有两种实现机制:
JDK动态代理基于接口实现,通过java.lang.reflect.Proxy
类和InvocationHandler
接口。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JdkProxy implements InvocationHandler {
private Object target;
public Object bind(Object target) {
this.target = target;
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this
);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
beforeInvoke(method);
Object result = method.invoke(target, args);
afterInvoke(method);
return result;
}
private void beforeInvoke(Method method) {
// 前置处理
}
private void afterInvoke(Method method) {
// 后置处理
}
}
// 使用示例
RealSubject realSubject = new RealSubject();
Subject proxy = (Subject) new JdkProxy().bind(realSubject);
proxy.request();
CGLIB库是一个强大的高性能代码生成库,可以在运行期扩展Java类与实现Java接口。它可以创建出一个被代理类的子类,因此不需要接口也能进行代理。CGLIB常用于Spring AOP框架中,对于没有实现接口的目标类也能提供代理支持。
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CglibProxy implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
beforeInvoke(method);
Object result = proxy.invokeSuper(obj, args);
afterInvoke(method);
return result;
}
private void beforeInvoke(Method method) {
// 前置处理
}
private void afterInvoke(Method method) {
// 后置处理
}
public Object createProxy(Class<?> clazz) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
// 使用示例
RealSubject realSubject = (RealSubject) new CglibProxy().createProxy(RealSubject.class);
((Subject) realSubject).request();
}
// 注意:这里假设RealSubject并未实现任何接口
Java代理设计模式是一种重要的设计思想,它帮助开发者在不影响原始类的情况下,对类的行为进行扩展和控制。在实际开发中,无论是通过静态代理还是动态代理,都能在很多场合发挥重要作用,尤其是在框架设计、服务治理、性能优化以及AOP等领域得到广泛应用。学习并掌握代理模式有助于提升代码的灵活性和可维护性。