单例模式的三种实现方式及其优缺点
public class SingletonDemo {
/**
* @param args
*/
public static void main(String[] args) {
SingletonEnum.INSTANCE.setmName("enum");
SingletonInner.getInstance().setmName("inner");
SingletonDoubleCheck.getInstance().setmName("doubleCheck");
}
/*
* 单例模式考虑点:
* 1. 线程安全:Synchronized关键字,Enum,静态内部类
* 2. 延迟加载:减少负载和消耗
* 3. 自动序列化(Serializable和transient)
* 4. 防止反射强行调用构造器
* 3、4点只有枚举可以实现
*/
/*
* 枚举实现单例
*/
public static enum SingletonEnum {
INSTANCE;
private String mName;
public String getmName() {
return mName;
}
public void setmName(String mName) {
this.mName = mName;
}
}
/*
* 双重检查锁:单例模式中需要new的情况非常少,第一层锁可以减少锁的次数
*/
public static class SingletonDoubleCheck {
private static volatile SingletonDoubleCheck singleton = null;
private SingletonDoubleCheck() {
}
public static SingletonDoubleCheck getInstance() {
if (singleton == null) {
synchronized (SingletonDoubleCheck.class) {
if (singleton == null) {
singleton = new SingletonDoubleCheck();
}
}
}
return singleton;
}
private String mName;
public String getmName() {
return mName;
}
public void setmName(String mName) {
this.mName = mName;
}
}
/*
* 内部类方式实现
*/
public static class SingletonInner {
private static class Holder {
private static SingletonInner singleton = new SingletonInner();
}
private SingletonInner() {
}
public static SingletonInner getInstance() {
return Holder.singleton;
}
private String mName;
public String getmName() {
return mName;
}
public void setmName(String mName) {
this.mName = mName;
}
}
}
工厂模式实例
观察者模式
- 在Java中通过Observable类和Observer接口实现了观察者模式,Observer对象监视着Observable对象的变化,当Observable对象发生变化时,Observer得到通知,就可以进行相应的工作。
- Observable类—-程序中的被观察者类需要继承这个类
- Observer接口—-观察者接口,观察者需要实现这个接口并重写其中的update()方法
- 可以在main函数中通过调用被观察者的addObserver方法添加观察者,当被观察者发生变化时要调用setChanged()方法标记此Observable对象已改变,并调用notifyObservers()通知所有观察者
自定义代码实现观察者模式:
// 被观察者接口 public interface Subject { public void registerObserver(Observer o); public void removeObserver(Observer o); public void notifyAllObservers(); } // 观察者接口 public interface Observer { public void update(Subject s); } // 猎头类 public class HeadHunter implements Subject { private ArrayList<Observer> userList; private ArrayList<String> jobs; public HeadHunter(){ userList = new ArrayList<Observer>(); jobs = new ArrayList<String>(); } @Override public void registerObserver(Observer o) { userList.add(o); } @Override public void removeObserver(Observer o) {} @Override public void notifyAllObservers() { for(Observer o: userList){ o.update(this); } } public void addJob(String job) { this.jobs.add(job); notifyAllObservers(); } public ArrayList<String> getJobs() { return jobs; } public String toString(){ return jobs.toString(); } } // 求职者类 public class JobSeeker implements Observer { private String name; public JobSeeker(String name){ this.name = name; } @Override public void update(Subject s) { System.out.println(this.name + " got notified!"); //print job list System.out.println(s); } } // 主函数 public class Main { public static void main(String[] args) { HeadHunter hh = new HeadHunter(); hh.registerObserver(new JobSeeker("Mike")); hh.registerObserver(new JobSeeker("Chris")); hh.registerObserver(new JobSeeker("Jeff")); //每次添加一个个job,所有找工作人都可以得到通知。 hh.addJob("Google Job"); hh.addJob("Yahoo Job"); } }
代理模式
- 代理模式就是为某个对象提供一个代理,以控制对这个对象的访问。 代理类和委托类有共同的父类或父接口,这样在任何使用委托类对象的地方都可以用代理对象替代。代理类负责请求的预处理、过滤、将请求分派给委托类处理、以及委托类执行完请求后的后续处理。
- 静态代理 由程序员创建或工具生成代理类的源码,再编译代理类。所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。
- 动态代理 动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以不存在代理类的字节码文件。代理类和委托类的关系是在程序运行时确定。
- java.lang.reflect.Proxy :Java 动态代理机制生成的所有动态代理类的父类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象, 其中newProxyInstance方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例
- java.lang.reflect.InvocationHandler:这是调用处理器接口,它自定义了一个 invoke 方法,用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对委托类的代理访问。每次生成动态代理类对象时都要指定一个对应的调用处理器对象。
适配器模式
- 适配器模式:将一个类的接口,转换成客户期望的另外一个接口。适配器让原本接口不兼容的类可以很好的合作;
两种方式:①类的适配器模式(采用继承实现)②对象适配器(采用对象组合方式实现); - 使用场景
- 系统需要使用现有的类,而这些类的接口不符合系统的接口。
- 想要建立一个可以重用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作
- 使用第三方组件,组件接口定义和自己定义的不同,不希望修改自己的接口,但是要使用第三方组件接口的功能。
装饰器模式VS代理模式
- 装饰器模式关注于在一个对象上动态的添加方法,是继承关系的一个替代方案;然而代理模式关注于控制对对象的访问,并不提供对象本身的增强功能。
- 对装饰器模式来说,装饰者和被装饰者都实现同一个接口; 对代理模式来说,代理类和真实处理的类都实现同一个接口
参考链接
- Java动态代理