23种常用的设计模式

23种设计模式总体可以分为三类: 一、创建型模式工厂模式、抽象工厂、单例模式、建造者模式、原型模式 二、结构型模式装饰器模式、适配器模式、代理模式、外观模式、

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