23种设计模式总体可以分为三类:
一、创建型模式
工厂模式、抽象工厂、单例模式、建造者模式、原型模式
二、结构型模式
装饰器模式、适配器模式、代理模式、外观模式、桥接模式、组合模式、享元模式
三、行为型模式
策略模式、观察者模式、模板方法模式、责任链模式、迭代子模式、备忘录模式、命令模式、访问者模式、中介者模式、状态模式、解释器模式
下面主要介绍以上9种红色字体的设计模式。
(1)工厂模式:定义一个创建对象的接口,让子类决定具体实例化哪一个对象。
public interface Sender{ void sender(); } public class SenderFactory{ //创建简单工厂 public Sender produce(String type){ if(type.equals("mail")){ return new MailSender(); }else if(type.equals("msg")){ return new MsgSender(); }else{ return null; } } }
(2)抽象工厂:为一组相关或相互依赖的对象提供一个接口,且无需指定他们的具体实现类。
//定义实现功能的接口 public interface Sender{ void sender(); } //定义生产工厂的接口,提供一个返回上面接口功能的方法,比如Sender public interface Provider{ Sender produce(); } //扩展发送邮件的实现类 public class MailSenderFactory implements Provider{ @Override Sender produce(){ return new MailSender(); } }
(3)单例模式:确保一个类只存在一个实例(介绍两种线程安全的单例模式)
1.使用volatile关键字实现线程安全的单例模式
public class SingletonInstance03 { private static volatile SingletonInstance03 singletonInstance03= null; //将这个变量定义为线程可见的 private SingletonInstance03(){} public static SingletonInstance03 getInstance(){ if(singletonInstance03 == null){ //对这个实例加锁 synchronized (singletonInstance03){ if(singletonInstance03 == null){ singletonInstance03 = new SingletonInstance03(); } } } return singletonInstance03; } }
2.使用内部类持有单例实例来实现线程安全的单例模式。
public class SingletonInstance04 { private SingletonInstance04(){} private static class InstanceHolder{ public static SingletonInstance04 singletonInstance04 = new SingletonInstance04(); } public static SingletonInstance04 getInstance(){ return InstanceHolder.singletonInstance04; } }
(4)适配器模式:将一个类的接口转换成客户端所期待的另一个接口。(分为类的适配器模式、对象的适配器模式、接口的适配器模式)
1.类的适配器模式:使用适配器类继承一个类同时实现一个接口。
public class Sourceable{ public void method1(){System.out.println("sourceable的方法");} } public interface Targetable{ void method1(); void method2(); } public class Adapter extends Sourceable implements Targetable{ @Override public void method2(){ System.out.println("类的适配器的method2方法"); } }
2.对象的适配器模式:适配器类中拥有被适配类的实例,通过构造器将被适配类的实例传入进来
public class Source{ public void method1(){ System.out.println("对象的适配器的method1方法"); } } public interface Targetable{ void method1(); void method2(); } public class Adapter implements Targetable{ private Source source; public Adapter(Source source){ this.source = source; } @Override void method1(){ source.method1(); } @Override void method2(){ System.out.println("接口中方法2的实现"); } }
3.接口的适配器模式:通过一个抽象类先去实现接口
public interface Sourceable{ void method1(); void method2(); } public abstract class AdapterForInterface implements Sorceable{ @Override void method1(){} @Override void method2(){} } public class SourceSub1 extends AdapterForInterface{ @Override void method1(){ System.out.println("重写抽象类的方法1"); } }
(5)装饰器模式:给一个对象动态的增加新的功能,要求装饰对象和被装饰对象实现共同的接口,并且装饰对象持有被装饰对象的实例。
public class Source{ //被装饰类 public void decorated(){ System.out.println("被装饰方法。"); } } public class Decorator{ private Source souce; public Decorator(Source source){ this.source = source; } public void decorator(){ System.out.println("装饰前。。。"); source.decorated(); System.out.println("装饰后。。。"); } }
(6)代理模式:在不改变源码的情况下,为原对象提供一个代理类,替原对象进行操作。(分类静态代理,JDK动态代理,CGLib动态代理)
1.静态代理:在代理前已经知道了被代理的类,代理类重写了被代理类的接口的方法
public interface UserService{ void addUser(User user); } public class UserServiceImpl{ void addUser(User user){ System.out.println("添加用户成功!"); } } public class UserServiceImplProxy implements UserService{ private UserService userService; public UseServiceImpProxy(UserService userService){ this.userService = userService; } @Override void addUser(User user){ System.out.println("进行添加用户前的操作..."); userService.addUser(user); System.out.println("进行添加用户后的操作..."); } }
2.JDK动态代理:使用JavaJDK中自带的方式实现动态代理,关键点用到了Proxy类中的newInstanceProxy方法,并且代理类需要实现InvocationHandler接口。
public class UserServiceProxyFactory implements InvocationHandler{ private UserService userService; public UserService(UserService userService){ this.userService = userService; } public UserServiceImp getUserServiceImp(){ return (UserServiceImp )Proxy.newInstanceProxy(userService.getClass().getClassLoader(), userService.getClass().getInterfaces(), this); } public Object invoke(Object proxy,Method method,Object[] args){ Object obj = method.invoke(proxy,args); return obj; } }
3.CGLib动态代理:需要实现MethodInterceptor接口,重写intercept方法。
public class SayHello{ public void say(){ System.out.println("请先说你好!"); } } public class CgLibProxy implements MethodInterceptor{ public SayHello getProxy(){ Enchance en = new Enchance(); en.setSuperClass(SayHello.class); //设置被代理的类 en.setCallback(this); SayHello sayHello = (SayHello)en.create(); //创建被代理的类 return sayHello; } @Override public Object intercept(Object proxy,Method method,Object[] objs,MethodProxy methodProxy){ System.out.println("被代理前做的事..."); Object result = methodProxy.intercept(proxy,objs); System.out.println("被代理后做的事..."); return result; } }
动态代理与CGLib代理的区别:使用动态代理是被代理类实现了接口,使用Cglib代理时被代理类没有实现接口,如上的UserServiceImp和SayHello类。
JDK动态代理产生对象的效率比Cglib高,但是由于CGLib采用ASM字节码生成框架操作起来效率比JDK动态代理高。
(7)策略模式:定义了一些列算法,并将它们封装起来,是的它们之间可以相互替换
public interface ICalculator{ int calculate(String exp); } public abstract class AbstractCalculate{ public int[] split(String exp,String opt){ String[] opts = exp.split(opt); int[] ops = new int[2]; ops[0] = Integer.parseInt(opts[0]); ops[1] = Integer.parseInt(opts[1]); return ops; } } public class Plus extends AbstractCalculate implements Icalculator{ @Override public int calculate(String exp){ int[] ints = split(exp,"\+"); return ints[0] + ints[1]; } } public class Minus extends AbstractCalculate implements Icalculator{ @Override public int calculate(String exp){ int[] ints = split(exp,"\-"); return ints[0] + ints[1]; } }
(8)模板方法模式:定义一个算法的骨架,并将一些步骤延迟到子类中,使得子类可以不改变算法的结构就能重定义算法的某些步骤。(比如JDK中经典的AQS框架)
public abstract class AbstractCalculate{ public int[] split(String exp,String opt){ int[] ops = new int[2]; String opts = exp.split(opt); ops[0] = Integer.parseInt(opts[0]); ops[1] = Integer.parseInt(opts[1]); return ops; } abstract int calculateHelper(int num1,int num2){} public final int calculate(String exp,String opt){ int[] ints = split(exp,opt); return calculateHelper(ints[0],ints[1]); } } public class Plus extends AbstractCalculate{ @Override int calculateHelper(int num1,int num2){ return num1 + num2; } }
(9)观察者模式:定义对象间一种一对多的依赖关系,使得每一个对象的状态改变,每一个依赖它的对象都能得到通知并被自动更新。
public interface Observe{ void update(); } public class Observe1 implements Observe{ @Override public void update(){ System.out.println("依赖的对象1接收到了改变的通知"); } } public class Observe2 implements Observe{ @Override public void update(){ System.out.println("依赖的对象2接收到了改变的通知"); } } public interface Subject{ void addObserve(Observe observe); void remObserve(Observe observe); void notifyObserve(); void operation(); } public abstract class AbstractSubject implements Subject{ private Vector<Observe> vector = new Vector<>(); @Override void addObserve(Observe observe){ vector.add(observe); } @Override void remObserve(Observe observe){ vector.remove(observe); } @Override void notifyObserve(){ Enumeration<Observe> elements = vector.elements(); while(elements.hasMoreElements()){ elements.nextElements().update(); } } } public class MySubject extends AbstractSubject{ @Override public void operation() { System.out.println("update itself"); notifyObserve(); } }