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();
}
}