设计模式
- 单例模式
- 实现
- 饿汉式
- 懒汉式
- 双重检测
- 工厂模式
- 简单工厂模式
- 抽象工厂
- 代理模式
- 静态代理
- 动态代理
- JDK动态代理原理
- cglib代理原理
单例模式
单例模式用来保证类在内存中只能有一个对象,因为对象的创建和销毁都会占用系统资源,一些昂贵的资源可以使用单例模式,节省系统资源
特点:
- 单例类只能有一个实例。
- 单例的类只能自己创建自己的实例。
- 单例类必须能够提供自己的唯一实例给其他类
使用场景
- Spring中的bean使用到了单例模式
- 计数器使用到了单例模式
- servlet也是一个单例模式
实现
- 提供一个本类的唯一实例
- 私有化构造,防止外界随意创建本类的实例
- 提供一个公开的静态的方法来让外界获取本类的唯一实例
饿汉式
饿汉式单例模式就是在类加载的时候就立即初始化,并且创建单例对象。不管你有没有用到,都先建好了再说。它绝对线程安全,在线程还没出现以前就实例化了,不可能存在访问安全问题。
优点:线程安全,没有加任何锁、执行效率比较高。
缺点:类加载的时候就初始化,不管后期用不用都占着空间,浪费了内存。
懒汉式
懒汉式,顾名思义就是实例在用到的时候才去创建,“比较懒”,用的时候才去检查有没有实例,如果有则直接返回,没有则新建。
双重检测
兼顾性能和线程安全问题
public class Singleton{// 提供一个本类的唯一实例 ,volatile 锁private volatile static final Singleton instance = null;// 私有化构造,防止外界随意创建本类的实例private Singleton(){}// 提供一个公开的静态的方法来让外界获取本类的唯一实例public static getInstance(){if(instance == null){// 锁住临界资源synchronized(Singleton.class){instance = instance == null ? instance = new Singleton() : instance;}}return instance;}
}
工厂模式
定义一个用于创建对象的接口,然子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
工厂模式有一个工厂类,工厂类知道产品类的具体实现细节,并决定何时实例化哪一个类。
简单工厂模式
简单工厂模式:又称为静态工厂方法模式,它属于类创建型模式。
在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个工厂类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
有一个父类,这个父类有多个子类,还有一个工厂类,工厂类中创建了父类对象,但是没有实例化,要用到对象的时候,根据传进来的参数不同,选择实例化不同的子类
public interface IVersion {void test();
}public class UserDao1 implements IVersion{@Overridepublic void test() {System.out.println("version1...");}
}public class UserDao2 implements IVersion{@Overridepublic void test() {System.out.println("version2...");}
}public class UserDao3 implements IVersion{@Overridepublic void test() {System.out.println("version3...");}
}/**工厂类**/
public class MyFactory {/*** 声明常量代替版本号*/public final static int V_ONE = 1;public final static int V_TWO = 2;public final static int V_THREE = 3;/*** 创建公开的静态方法* @return*/public static IVersion getInstance(Integer version){IVersion userDao = null;switch (version){case V_ONE:userDao = new UserDao1();break;case V_TWO:userDao = new UserDao2();break;case V_THREE:userDao = new UserDao3();break;default:System.out.println("简单工厂模式");}return userDao;}
}
抽象工厂
工厂方法模式针对的是一个产品等级结构;
而抽象工厂模式则是针对的多个不同产品等级结构。
或者话,普通工厂模式只能生产具体某一类产品。但是抽象工厂,可以生产多个不同类的产品。打破了工厂与产品之间一对一的关系。
要添加新的大类,就要修改工厂类,违反了开闭原则。
①创建鼠标类的共同接口
//鼠标的接口
interface mouse {public void show();
}②创建戴尔鼠标类实现鼠标接口,即具体的产品类
//具体的产品类(戴尔鼠标),来实现鼠标这个抽象接口
class Dellmouse implements mouse {public void show() {System.out.println("这是个戴尔鼠标");}
}③创建惠普鼠标类来实现鼠标接口,即具体的产品类
//具体的产品类(惠普鼠标),来实现鼠标这个抽象接口
class Hpmouse implements mouse {public void show() {System.out.println("这是个惠普鼠标");}
}④创建键盘类的共同接口
//键盘的接口
interface keyboard {public void show();
}⑤创建戴尔键盘类来实现键盘接口,即具体的产品类
//具体的产品类(戴尔键盘),来实现键盘这个抽象接口
class Dellkeyboard implements keyboard {public void show() {System.out.println("这是个戴尔键盘");}
}⑥创建惠普键盘类来实现键盘接口,即具体的产品类
//具体的产品类(惠普键盘),来实现键盘这个抽象接口
class Hpkeyboard implements keyboard {public void show() {System.out.println("这是个惠普键盘");}
}⑦创建抽象工厂类共同接口
//抽象工厂类接口
interface PCFactory {public mouse createmouse();public keyboard createkeyb();
}⑧创建具体工厂类A,来实现抽象工厂类接口
//具体工厂类A,来实现抽象工厂类接口class FactoryA implements PCFactory {public mouse createmouse() { //实现接口的方法return new Dellmouse(); //返回创建具体产品类1}public keyboard createkeyb() { //实现接口的方法return new Dellkeyboard(); //返回创建具体产品类2}
}⑨创建具体工厂类B,来实现抽象工厂类接口
//具体工厂类B,来实现抽象工厂类接口
class FactoryB implements PCFactory {public mouse createmouse() { //实现抽象接口方法return new Hpmouse(); //返回创建具体类}public keyboard createkeyb() { //实现抽象接口方法return new Hpkeyboard(); //返回创建具体类}
}⑩用户端的调用
//用户端的调用
public class user {public static void main(String[] args) {PCFactory f=new FactoryA(); f.createmouse().show(); //用户类只跟接口打交道,只需调用接口的方法f.createkeyb().show();PCFactory ff=new FactoryB();ff.createmouse().show();ff.createkeyb().show();}
}
代理模式
代理模式简单的说就是可以在不改变原来代码的情况下,通过引入代理类来扩展功能。
静态代理
比如我们有一个接口角色:增删改查业务, 然后有一个实现类去完成这些具体的实现。
现在我们需要为它增加日志功能,
我们先写一个代理类去继承接口,然后在里面加上增删改查的实现类对象。然后再用对象调用方法,再在方法里加上新的功能。
- 创建一个抽象角色,比如咋们平时做的用户业务,抽象起来就是增删改查!
//抽象角色:增删改查业务
public interface UserService {void add();void delete();void update();void query();
}
- 我们需要一个真实对象来完成这些增删改查操作
//真实对象,完成增删改查操作的人
public class UserServiceImpl implements UserService {public void add() {System.out.println("增加了一个用户");}public void delete() {System.out.println("删除了一个用户");}public void update() {System.out.println("更新了一个用户");}public void query() {System.out.println("查询了一个用户");}
}
- 需求来了,现在我们需要增加一个日志功能,怎么实现!
- 思路1 :在实现类上增加代码 【麻烦!】
- 思路2:使用代理来做,能够不改变原来的业务情况下,实现此功能就是最好的了!
- 设置一个代理类来处理日志! 代理角色
//代理角色,在这里面增加日志的实现
public class UserServiceProxy implements UserService {private UserServiceImpl userService;public void setUserService(UserServiceImpl userService) {this.userService = userService;}public void add() {log("add");userService.add();}public void delete() {log("delete");userService.delete();}public void update() {log("update");userService.update();}
动态代理
- 动态代理的角色和静态代理的一样 .
- 动态代理的代理类是动态生成的 . 静态代理的代理类是我们提前写好的
- 动态代理分为两类 : 一类是基于接口动态代理 , 一类是基于类的动态代理
基于接口的动态代理----JDK动态代理
基于类的动态代理–cglib
JDK的动态代理只能用来代理接口,
而CGLIB的动态代理既可以代理接口也可以用来代理类
JDK动态代理原理
JDK动态代理的核心是InvocationHandler接口和Proxy类,如果代理的类没有实现InvocationHandler接口时,就会使用CGLIB代理
原理:
通过一个代理类区实现InvocationHandler接口,去实现接口的invoke方法,这个方法有三个参数(类,方法,参数),然后通过反射来调用
//这是接口
public interface A{void hello();}
//这是接口实现类
public class B implements A{
@override
void hello()hello
)}//JDK动态代理过程
代理类implements InvocationHandler{
invoke(proxy , method , argsX){//类 ,方法, 参数
//代理开始method.invoke( target , args); //要代理的对象, 参数
//代理结束}
}
cglib代理原理
cglib是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法。因为是继承,所以该类或方法最好不要声明成final。
原理:待续