1.常见模式及使用场景
1.1单例模式 :
为何单例 : 系统中只存在某个类的唯一实例(对象)。如System类,在应用系统中只需要持有其一个实例即可,因为多个实例能执行的操作与结果都是一样的。
如何实现 : 因为整个应用系统只提供一个实例,那么需要我们创建一个实例,且显示私有化构造方法,并提供外界获取该实例的方法。下面是具体代码实现。
(1)饿汉式:饿了,那么在类加载时就创建一个实例。
public class EHanDanli {
//此处定义类变量实例并直接实例化,在类加载的时候就完成了实例化并保存在类中
private static EHanDanli dl = new EHanDanli();
//定义无参构造器,用于单例实例
private EHanDanli(){}
//定义公开方法,返回已创建的单例
public static EHanDanli getInstance(){
return dl;
}
}
(2) 懒汉式: 啥时候用啥时候创建
public class LHanDanli {
//定义一个私有类变量来存放单例,私有的目的是指外部无法直接获取这个变量,而要使用提供的公共方法来获取
private static LHanDanli dl = null;
//定义私有构造器,表示只在类内部使用,亦指单例的实例只能在单例类内部创建
private LHanDanli(){}
//定义一个公共的公开的方法来返回该类的实例,由于是懒汉式,需要在第一次使用时生成实例,所以为了线程安全,使用synchronized关键字来确保只会生成单例
public static synchronized LHanDanli getInstance(){
if(dl == null){
dl = new LHanDanli();
}
return dl;
}
}
(3) 双重非空判断并加锁:在懒汉式中我们每次获取该实例时都会进行同步和判断这样会降低获取速率。
public class SLHanDanli {
//volatile 关键字保证多线程的可见性,避免访问到的是一个未初始化的对象
private static volatile SLHanDanli dl = null;
private SLHanDanli(){}
public static SLHanDanli getInstance(){
//如果实例化已经完成,那么直接返回该实例。
if(dl == null){
//加锁进行实例化
synchronized (SLHanDanli.class) {
//这里的判断是避免,当线程A、B同时进入9处时,A先获取锁后,进行实例化,
//然后释放锁,此时B获取锁后避免再次实例化。
if(dl == null){
dl = new SLHanDanli();
}
}
}
return dl;
}
}
1.2工厂方法 :
通过工厂创建实例,使对象的创建与使用分离,实现解耦。经典案例就是Shiro的Factory接口
package org.apache.shiro.util;
//通过接口及泛型定义该接口的能力
public interface Factory<T> {
T getInstance();
}
//抽象工厂,这里的singleton就是定制化操作,该类的主要作用还是实现对象的创建
public abstract class AbstractFactory<T> implements Factory<T> {
private boolean singleton;
private T singletonInstance;
public AbstractFactory() {
this.singleton = true;
}
public boolean isSingleton() {
return singleton;
}
public void setSingleton(boolean singleton) {
this.singleton = singleton;
}
//定义对象创建过程
public T getInstance() {
T instance;
if (isSingleton()) {
if (this.singletonInstance == null) {
this.singletonInstance = createInstance();
}
instance = this.singletonInstance;
} else {
instance = createInstance();
}
if (instance == null) {
String msg = "Factory 'createInstance' implementation returned a null object.";
throw new IllegalStateException(msg);
}
return instance;
}
//这里是模板方法,将实际操作放到子类实现,以实现多样化操作。
protected abstract T createInstance();
}
1.3模板模式
定义某个需求的逻辑实现步骤,将具体的实现交由子类完成。
具体的代码可参看上面的示例代码,getInstance()方法需要条件化创建实例【即createInstance()】,但是实例的创建可能有多种方式,故这里抽象出来,将具体创建步骤交由子类实现。
1.4代理模式
在不改变源码的情况下,实现对目标对象的功能扩展。
有三种实现方式
(1)静态代理 : 代理类与目标类实现同一接口。代码耦合性高,若接口增加某项能力,那么原实现的类都需要增加代码。
public interface ISinger {
void sing();
}
/**
* 目标对象实现了某一接口
*/
public class Singer implements ISinger{
public void sing(){
System.out.println("唱一首歌");
}
}
/**
* 代理对象和目标对象实现相同的接口
*/
public class SingerProxy implements ISinger{
// 接收目标对象,以便调用sing方法
private ISinger target;
public UserDaoProxy(ISinger target){
this.target=target;
}
// 对目标对象的sing方法进行功能扩展
public void sing() {
System.out.println("向观众问好");
target.sing();
System.out.println("谢谢大家");
}
}
// ======================测试类===============================
public class Test {
public static void main(String[] args) {
//目标对象
ISinger target = new Singer();
//代理对象
ISinger proxy = new SingerProxy(target);
//执行的是代理的方法
proxy.sing();
}
}
(2)JDK动态代理 : 通过jdk提供的Proxy实现代理
public class Test{
public static void main(String[] args) {
Singer target = new Singer();
ISinger proxy = (ISinger) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
//此处为具体方法
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("向观众问好");
//执行目标对象方法
Object returnValue = method.invoke(target, args);
System.out.println("谢谢大家");
return returnValue;
}
});
proxy.sing();
}
}
(3)Cglib代理
/**
* 目标对象,没有实现任何接口
*/
public class Singer{
public void sing() {
System.out.println("唱一首歌");
}
}
/**
* Cglib子类代理工厂
*/
public class ProxyFactory implements MethodInterceptor{
// 维护目标对象
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
// 给目标对象创建一个代理对象
public Object getProxyInstance(){
//1.工具类
Enhancer en = new Enhancer();
//2.设置父类
en.setSuperclass(target.getClass());
//3.设置回调函数
en.setCallback(this);
//4.创建子类(代理对象)
return en.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("向观众问好");
//执行目标对象的方法
Object returnValue = method.invoke(target, args);
System.out.println("谢谢大家");
return returnValue;
}
}
/**
* 测试类
*/
public class Test{
public static void main(String[] args){
//目标对象
Singer target = new Singer();
//代理对象
Singer proxy = (Singer)new ProxyFactory(target).getProxyInstance();
//执行代理对象的方法
proxy.sing();
}
}
1.5装饰器模式
装饰器模式也是对目标方法进行增强,只不过这里没有代理对象的生成。代码实现如下
/**
* 目标接口:房子
*/
public interface House {
void output();
}
/**
* 房子实现类
*/
public class DonghaoHouse implements House {
@Override
public void output() {
System.out.println("这是董浩的房子");
}
}
/**
*装饰起类
*/
public class Decorator implements House {
private House house;
public Decorator(House house){
this.house = house;
}
@Override
public void output() {
System.out.println("这是针对房子的前段装饰增强");
house.output();
System.out.println("这是针对房子的后段装饰增强");
}
}
public class Clienter {
public static void main(String[] args) {
House donghaoHouse = new DonghaoHouse();
House decorator = new Decorator(donghaoHouse);
decorator.output();
}
}