• 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();
        }
    }
  • 相关阅读:
    将Excel表中的数据导入到数据库
    别人面试的学习路线
    和同门一起做的PHP网站
    正则表达式
    python 编码形式简单入门
    游戏开发者面临的几大问题
    quick-cocos2d-x与 cocos2d-x的关系
    cocos2dx中的坐标系统
    重载new和delete来检测内存泄漏
    VS下使用Google Protobuf完成SOCKET通信
  • 原文地址:https://www.cnblogs.com/HubuSugar/p/11797767.html
Copyright © 2020-2023  润新知