什么是设计模式?
设计模式是一套被反复使用,多数人知晓的,进过分类编目的,代码设计经验的总结,使用设计模式是为了可重用代码,让代码更容易被他人理解,保证代码可靠性。
设计模式的分类
创建型模式:工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式。
结构型模式:适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,享元模式。
行为型模式:策略模式,模板方法模式,观察者模式,迭代子模式,责任链模式,命令模式,备忘录模式,状态模式,访问者模式,中介者模式,解释器模式。
设计模式六大原则
1.开闭原则:开闭原则就是说对扩展开发,对修改关闭。
2.里氏代换原则:面向对象设计的基本原则之一。
3.依赖倒转原则:针对接口编程,依赖于抽象而不依赖于具体。
4.接口隔离原则:使用多个隔离的接口,比使用单个接口要好。
5.迪米特法则:一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。
6.合成复用原则:原则是尽量使用合成,集合的方式,而不是使用继承。
单例模式
单例保证一个对象jvm中只能有一个实例,常见单例懒汉式,饿汉式
懒汉式,就是需要时才会去实例化,线程不安全
饿汉式,就是当class文件被加载的时候,初始化,天生线程安全
//懒汉式
class Singleton {
private Singleton() { }
private static Singleton s = null;
public static Singleton getSingleton() {
if(s== null) {
synchronized (Singleton.class) {
if(s==null) {
s = new Singleton();
}
}
}
return s;
}
}
//饿汉式
class Singleton {
private Singleton() { }
private static Singleton s = new Singleton();
public static Singleton getSingleton() {
return s;
}
}
工厂模式
//定义一个接口
interface Fruits{
void eat();
}
class Apple implements Fruits {
public void eat() {
System.out.println("吃苹果");
}
}
class Banana implements Fruits {
public void eat() {
System.out.println("吃香蕉");
}
}
class Fruitsfactory {
public static Fruits getFruits(String type) {
Fruits f = null;
switch (type) {
case "apple":
f = new Apple();
break;
case "banana":
f = new Banana();
break;
}
return f;
}
}
public class Demo {
public static void main(String[] args) throws Exception {
//传入不同的参数获取不同的对象
Fruits fruits = Fruitsfactory.getFruits("apple");
fruits.eat();
}
}
代理模式
通过代理控制对象的访问,可以详细访问某个对象的方法,在这个方法调用处理,或调用后处理,即aop微实现,aop核心技术面向切面编程。
代理分类:静态代理,动态代理(jdk动态代理,cglib)
//静态代理
interface Animal {
void run();
}
class Person implements Animal{
public void run () {
System.out.println("跑步");
}
}
class PersonAgency implements Animal {
private Person p;
public PersonAgency(Person p) {
this.p=p;
}
public void run() {
System.out.println("跑步前");
p.run();
System.out.println("跑步后");
}
}
public class Demo {
public static void main(String[] args) throws Exception {
Person p = new Person();
PersonAgency pa = new PersonAgency(p);
pa.run();
}
}
jdk动态代理
interface Animal {
void run();
}
class Person implements Animal{
public void run () {
System.out.println("跑步");
}
}
class JDKPersonAgency implements InvocationHandler {
private Object obj;
public JDKPersonAgency(Object obj) {
this.obj = obj;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("跑步前");
Object object = method.invoke(obj, args);
System.out.println("跑步后");
return object;
}
}
public class Demo {
public static void main(String[] args) throws Exception {
Person p = new Person();
JDKPersonAgency jpa = new JDKPersonAgency(p);
Animal a = (Animal) Proxy.newProxyInstance(p.getClass().getClassLoader(), p.getClass().getInterfaces(), jpa);
a.run();
}
}
cglib动态代理
interface Animal {
void run();
}
class Person implements Animal{
public void run () {
System.out.println("跑步");
}
}
class Cglib implements MethodInterceptor{
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
System.out.println("跑步前");
Object obj = arg3.invokeSuper(arg0, arg2);
System.out.println("跑步后");
return obj;
}
}
public class Demo {
public static void main(String[] args) throws Exception {
Person p = new Person();
Cglib cglib = new Cglib();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(p.getClass());
enhancer.setCallback(cglib);
Animal a = (Animal) enhancer.create();
a.run();
}
}
CGLIB与JDK动态代理区别
java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理,而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
如果目标对象实现了接口,默认情况下会采用jdk的动态代理实现aop
如果目标对象实现了接口,可以强制使用cglib实现aop
如果目标对象没有实现接口,必须采用cglib库,spring会自动在jdk动态代理和cglib之间转换。