常见设计模式
设计模式通常是对于某一类的软件设计问题的可重用的解决方案,将设计模式引入软件设计和开发过程,其目的就在于要充分利用已有的软件开发经验。大学期间曾经学习与了解过一些设计模式,但也一知半解,只觉得这是一个很高深的东西。不知不觉中,设计模式已经满满当当充斥在工作中的各个程序模块中。最近抽出时间,将一些简单的设计模式整理出来。作为笔记,记录下来。
1. 单例模式
如果一个类始终只能创建一个实例,则这个类被称为单例类,这种模式就被称为单例模式。
一般建议单例模式的方法命名为:getInstance(),这个方法的返回类型肯定是单例类的类型了。getInstance方法可以有参数,这些参数可能是创建类实例所需要的参数,当然,大多数情况下是不需要的。
/**
* 单例模式
* @author xieyini
*
*/
public class Singleton {
public static void main(String[] args) {
// Singleton对象不能通过构造器,只能通过getInstance方法
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
// 检查两个对象是否一致
System.out.println(s1 == s2);
}
// 使用一个变量来缓存曾经创建的实例
private static Singleton instance;
// 将构造器用private修饰隐藏构造器
private Singleton() {
System.out.println("Singleton构造器被创建");
}
// 提供一个静态方法,用于返回Singleton实例
public static Singleton getInstance() {
// 如果instance为null,则singleton对象还未被创建
// 如果instance不为null,则singleton对象已被创建
if (instance == null) {
// 创建一个Singleton对象,并对其缓存起来
instance = new Singleton();
}
return instance;
}
}
该设计模式的主要优势是,减少创建实例带来的系统开销。同时有利于我们跟踪单个实例生命周期。
2. 代理模式
代理模式是一种应用非常广泛的设计模式,当客户端代码需要调用某个对象时,客户端实际上不关心是否准确得到该对象,它只要一个能提供该功能的对象即可,此时我们就可返回该对象的代理(Proxy)。
代理就是一个Java对象代表另一个Java对象来采取行动。
/**
* 代理模式
* @author xieyini
*
*/
public class StudentProxy implements Student {
private Student student;
public StudentProxy(Student student) {
this.student = student;
}
public void sayHi() {
// 代理添加逻辑
System.out.println("Good Morning!");
// 代理类中的sayHi逻辑
student.sayHi();
}
public static void main(String[] args) {
Student student = new StudentProxy(new Girl());
student.sayHi();
}
}
// 首先定义一个接口
interface Student {
void sayHi();
}
// 再定义被代理的类
class Girl implements Student {
private String name = "Lisa";
public void sayHi() {
System.out.println("My name is " + name);
}
}
观察代码可以发现每一个代理类只能为一个接口服务,这样一来程序开发中必然会产生过多的代理,而且,所有的代理操作除了调用的方法不一样之外,其他的操作都一样,则此时肯定是重复代码。
解决方案:动态代理
动态代理包含一个接口与一个方法。
InvocationHandler接口
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
与静态代理类对照的是动态代理类,动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。动态代理类不仅简化了编程 工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。java.lang.reflect 包中的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力。
/**
* JDK动态代理代理类
*
* @author student
*
*/
public class BookFacadeProxy implements InvocationHandler {
private Object target;
/**
* 绑定委托对象并返回一个代理类
* @param target
* @return
*/
public Object bind(Object target) {
this.target = target;
//取得代理对象
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this); //要绑定接口(这是一个缺陷,cglib弥补了这一缺陷)
}
@Override
/**
* 调用方法
*/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result=null;
System.out.println("事物开始");
//执行方法
result=method.invoke(target, args);
System.out.println("事物结束");
return result;
}
}