zoukankan      html  css  js  c++  java
  • 设计模式:设计模式概述&JDK中的应用

    【概述】

         设计模式主要分为三大类:创建型、结构型、行为型

    【创建型】

         目的:对象怎么来的?创建对象时隐藏创建逻辑,不直接使用new。

         1.1 单例模式 Singleton:

            原理:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

            举例:java.lang.Runtime;

               Runtime rt = Runtime.getRuntime(); //每一个运行的java都会有唯一的一个运行时实例。运行过程中实例会受影响。
               源码:private static Runtime currentRuntime = new Runtime();  
                          public static Runtime getRuntime() {
                                return currentRuntime
                          }

         1.2 原型模式 Prototype:

            原理:用于创建重复的对象,同时又保证性能。实现了一个原型接口,该接口用于创建当前对象的克隆。浅拷贝(Cloneable)和深拷贝(Serializable读取二进制流)

            举例:Object.clone();  Spring框架bean装配时scope的类型:Singleton,ProtoType

       public static Shape getShape(String shapeId) {
          Shape cachedShape = shapeMap.get(shapeId);
          return (Shape) cachedShape.clone();
       }

         1.3 工厂模式 Factory:

            原理:创建对象时不会对客户端暴露创建逻辑,而且是通过使用一个统统的接口来指向新创建的对象。

            举例: java.lang.Class  

    Class clazz = new Object().getClass;
    Object obj = clazz.newInstance();  // 利用反射创建实例。

         1.4 抽象工厂模式 Abstract:

            原理:接口是负责创建一个相关对象的工厂,不需要显示指定他们的类。每个生成的工厂都能按照工厂模式提供对象。

            举例:java.text.NumberFormat;

    NumberFormat numberFormat = NumberFormat.getInstance(Locale.CANADA);
    源码:
      public static NumberFormat getInstance(Locale) {
            return getInstance(inLocale, NUMBERSTYLE); //返回的抽象数据类型,会进一步判断choice的类别来返回设置的格式。
      }

         1.5 建造者模式 Builder:

           原理:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的标识。顺序无关的对象可以都先创建好。

           举例:Java.lang.StringBuilder;

    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append(); //通过系统拷贝方法System.arrayCopy()方法生成一个新的字符序列

    【结构型】

        目的:对象和谁有关?关注类和对象,继承的概念被用来组合接口/对象获得新功能。

        2.1 适配器模式 Adapter:

          原理:作为两个不兼容的接口之间的桥梁。主要是解决正在服役的项目的问题。

          举例:java.util.Arrays.asList();    java.io.InputStreamReader(InputStream)

    String[] arr = {"1", "2", "3"};
    List<String> arrayList = Arrays.asList(arr);
    源码:
        public static <T> List<T> asList(T.. a) {
          return new ArrayList<>(a);  // 利用数组数据初始化elementData和size字段,这两个值是ArrayList的核心属性。
       }

        2.2 桥接模式 Bridage:

         原理:把抽象化与实现化解耦,使它们都可以独立的变化。

         举例:java.sql.Connection/DriverManager;

    try {
         Class.forName("com.mysql.jdbc.Driver");  // 装载进去,即具体的Driver装载到DriverManager中。
         String url = "";
         String user = "";
         String password = "";
         Connection con = DriverManager.getConnection(url, user, password);
    } catch (Exception e) {
    ...........
    }
    源码分析:DriverManager就相当于是一个Bridage Driver --> DriverManager(Bridage) --> Connection
    public class Driver extends NonRegisteringDriver implements java.sql.Driver {   static { try {        java.sql.DriverManager.registerDriver(new Driver); } catch (SQLException e) { ................ } } }

       2.3 过滤器模式 Filter:

         原理:使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把它们连接起来。

         举例:java.util.map(JDK8);

    Map<Integer, List<Person >> groupMap = persons.stream().collect(Collectors.groupingBy(Person::getGender));
    groupMap.forEach((k, v) -> { // k是分组的指标,v是list集合
        System.out.println(k);
        v.forEach(System.out::println);
    });

       2.4 组合模式 Composite:

         原理:创建了一个包含自己对象组的类。该类提供了修改相同对象组的方式。

         举例:java.util.Map;

    Map<String, String> map1 = new HashMap<String, String>();
    Map<String, String> map2 = new HashMap<String, String>();
    map1.putAll(m2); // 自己可以装配和自己类型相同的对象组

       2.5 装饰器模式 Decorator:

         原理:允许动态地向一个现有的对象添加新的功能,同时又不改变其结构。类似extends,但不需要产生大量子类,关键还是动态产生。

         举例:java.io.BufferedInputStream(InputStream);

    源码分析:
        public BufferedInputStream(InputStream in, int size) {
            super(in);  // inputStream类型的in对象
            if (size <= 0) {  
                throw new IllegalArgumentException("Buffer size <= 0");
            }
            buf = new byte[size];
        }
        public void close() throws IOException {
            byte[] buffer;
            while ( (buffer = buf) != null) {
                if (bufUpdater.compareAndSet(this, buffer, null)) {
                    InputStream input = in;  //实际操作的是in对象,close结构没变
                    in = null;
                    if (input != null)
                        input.close();
                    return;
                }
                // Else retry in case a new buf was CASed in fill()
            }
        }

       2.6 外观模式 Facade:

         原理:为复杂的模块获子系统提供外界访问的模块。

         举例:javax.servlet.http.HttpServletRequest;

    源码分析:
    public HttpServletRequest getRequest() {
       if (facade == null) {
            facade = new RequestFacade(this); // 里边有许多内部组件之间交互的public类型方法,但又不能对外开放。如setComet,setRequestedSessionId等。
       }
    }

       2.7 享元模式 Flyweight:

         原理:减少创建对象的数量,以减少内存占用和提供性能。尝试重用现有的同类对象,如果未找到匹配的对象,则创建新的对象。

         举例:java.lang.Integer;

    Integer integer = Integer.valueof(1);

    源码:
    assert IntegerCache.hight >=127;
    if (i >= IntegerCache.low && i <= IntegerCache.high) 
       return IntegerCache.cache[i + (-IntegerCache.low)];   // 先判断,满足条件就从缓存数据中取,不再创建新对象。
     return new Integer(i);

       2.8 代理模式 Proxy:

        原理:在代理模式中,我们创建具有目标对象的代理对象,以便向外界提供功能接口。

        举例:java.lang.reflect.InvocationHnadler;

    final ISomeService target = new SomeServiceImpl();  // 自由变量
            ISomeService proxy = (ISomeService) Proxy.newProxyInstance(target.getClass().getClassLoader(),
                    target.getClass().getInterfaces(),
                    new InvocationHandler() {
                        // 织入:交叉业务逻辑切入到主业务中。
                        @Override
                        public Object invoke(Object proxy, Method method,
                                Object[] args) throws Throwable {
                            SomeUtils.doTransaction();
                            Object result = method.invoke(target, args);
                            SomeUtils.doLog();
                            return result;
                        }  
            });
            proxy.doSome();
            proxy.doSecond();

    【行为型】

        目的:对象与对象在干吗?关注对象之间的通信

        3.1 责任链模式 Chain of Responsibility:

          原理:通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者.

          举例:java.util.logging.Logger;

    public void log(LogRecord record) {
            if (record.getLevel().intValue() < levelValue || levelValue == offValue) {
                return;
            }
            Filter theFilter = filter;
            if (theFilter != null && !theFilter.isLoggable(record)) {
                return;
            }
            // Post the LogRecord to all our Handlers, and then to
            // our parents' handlers, all the way up the tree.
            Logger logger = this;
            while (logger != null) {
                for (Handler handler : logger.getHandlers()) {
                    handler.publish(record);  //获取Handler的引用,交给其处理
                }
                if (!logger.getUseParentHandlers()) {
                    break;
                }
                logger = logger.getParent();
            }
        }

        3.2 命令模式 Command:

          原理: 数据驱动,以Command的形式包裹在对象中,并传给Invoker调用对象。Invoker对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。适用于:行为的记录、撤销、重做、事务等。

          举例:java.lang.runnable;   

                Runnable runable = () -> System.out.println(“具体命令”);  // 即Command (run)包裹在runnable对象中。
                Thread Thread1 = new Thread(runable); // 将包裹cmd的对象交给Thread,即Invoker
                Thread1.start(); // Invoker调用 cmd的方法。

        3.3 解释器模式 Interpreter:

          原理:提供了评估语言的语法或表达式的方法。实现了一个表达式接口,该接口解释了一个待定的上下文。常用于SQL解析、符号处理引擎等。

          举例:java.text.Format;  java.util.Pattern;

    Pattern pattern = Pattern.compile("regexExpression");  // 解释器的作用
    Matcher match = pattern.matcher("expresionString"); 
    Boolean result = match.matches();
    // Pattern实例是不可变的,并且支持并发和多线程安全,而Matcher不支持,则另一种表达方式
    Boolean result = Pattern.matches("regexExpression", "expresionString")

        3.4 迭代器模式 Iterator:

          原理:顺序访问集合对象的元素,不需要知道集合对象的底层表示。

          举例:java.util.Iterator;

    private abstract class HashIterator<E> implements Iterator<E> {
            Entry<K,V> next;        // next entry to return
            int expectedModCount;   // For fast-fail
            int index;              // current slot
            Entry<K,V> current;     // current entry
    
            HashIterator() {
                expectedModCount = modCount;
                if (size > 0) { // advance to first entry
                    Entry[] t = table;
                    while (index < t.length && (next = t[index++]) == null)
                        ;
                }
            }
    
            public final boolean hasNext() {
                return next != null;
            }
    
            final Entry<K,V> nextEntry() {
                if (modCount != expectedModCount)
                    throw new ConcurrentModificationException();
                Entry<K,V> e = next;
                if (e == null)
                    throw new NoSuchElementException();
    
                if ((next = e.next) == null) {
                    Entry[] t = table;
                    while (index < t.length && (next = t[index++]) == null)
                        ;
                }
                current = e;
                return e;
            }

        3.5 中介者模式 Mediator:

          原理:提供了一个中介类,该类处理不同类之间的通信。符合迪米特法则(最少知道原则),减少实体之间的相互作用。

          举例:java.util.concurrent.Executor;   java.util.Timer;  java.lang.reflect.Method; 

             Runnable runable = () -> System.out.println(“具体命令”);  // 即Command (run)包裹在runnable对象中。
             ExecoturService executorService = Executors.newSingleThreadExecutor();  // 中介类
             executorService.execute(runable);  // 中介类来执行

        3.6 备忘录模式 Memento:

          原理:保存一个对象的某个状态,以便在适当的时候恢复对象。

          举例:java.io.Serializable

    public class DemoBean implements Serializable {
        private static final long serialVersionUID = 1L;
        ................
    }
    
    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("D:/demoBean.txt")));  //可以备忘到文件,容器缓存中等
    oos.writeObject(demoBean) // 将对象demoBean保留下来
    
    ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("D:/demoBean.txt")));
    DemoBean demoBean = (DemoBean)ois.readObject();  // 恢复

        3.7 观察者模式 Observer:

          原理:当一个对象被修改时,会自动通知它依赖的对象。一般使用异步方式。

          举例:java.util.EventListener&java.uti.EventObject;   javax.servlet.http.HttpSessionBindingListener 

             1)事件对象

    import java.util.EventObject;
    
    public class MyEvent extends EventObject {
    
        private static final long serialVersionUID = 1L;
        private int sourceState;
        
        public MyEvent(Object source) {
            super(source);
            sourceState = ((Source)source).getFlag();
        }
        
        public int getSourceState() {
            return sourceState;
        }
    
    }
    View Code

             2)事件监听器(观察者)

    import java.util.EventListener;
    
    /**
     * 
     * @author Thief
     *
     */
    public class StateChangeListener implements EventListener {
    
        public void handleEvent(MyEvent event) {
            System.out.println("触发状态改变事件。。。");
            System.out.println("当前事件源状态为:" + event.getSourceState());
            System.out.println("。。。。。。。。。。。。。。。。。。。。。。。");
        }
    }
    View Code
    import java.util.EventListener;
    
    /**
     * 
     * @author Thief
     *
     */
    public class StateChangeToOneListener implements EventListener {
    
        public void handleEvent(MyEvent event) {
            System.out.println("触发状态变为1的事件。。。");
            System.out.println("当前事件源状态为:" + event.getSourceState());
            System.out.println("。。。。。。。。。。。。。。。。。。。。。。。");
        }
        
    }
    View Code

             3)事件源(被观察者)

    import java.util.EventListener;
    import java.util.HashSet;
    import java.util.Set;
    
    /**
     * 
     * @author Thief
     *
     */
    public class Source {
    
        private int flag = 0;
        Set<EventListener> listeners = new HashSet<EventListener>();
    
        /**
         * 注册事件监听器
         * 
         * @param listener
         */
        public void addStateChangeListener(StateChangeListener listener) {
            listeners.add(listener);
        }
        
        /**
         * 注册事件监听器
         * 
         * @param listener
         */
        public void addStateChangeToOneListener(StateChangeToOneListener listener) {
            listeners.add(listener);
        }
    
        /**
         * 当事件发生时,通知注册在事件源上的所有事件做出相应的反映
         */
        public void notifyListener() {
            for (EventListener listener : listeners) {
                try {
                    ((StateChangeListener)listener).handleEvent(new MyEvent(this));
                } catch (Exception e) {
                    if (flag == 1) {
                        ((StateChangeToOneListener)listener).handleEvent(new MyEvent(this));
                    }
                }
            }
        }
    
        /**
         * 改变状态
         */
        public void changeFlag() {
            flag = (flag == 0 ? 1 : 0);
            notifyListener();
        }
    
        public int getFlag() {
            return flag;
        }
    }
    View Code

        3.8 状态模式 State:

          原理:允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。

          举例:java.util.Iterator;

        3.9 策略模式 Strategy:

          原理:策略对象改变context对象的执行算法。

          举例:java.util.concurrent.ThreadPoolExecutor;  java.util.Comparator;

             Runnable runable = () -> System.out.println(“具体命令”);  // 即Command (run)包裹在runnable对象中。
             ThreadPoolExecutor executorService;
             executorService = new ThreadPoolExecutor(1,1,1L,TimeUnit.MINUTES,new ArrayBlockingQueue<1>, new ThreadPoolExecutor.AbortPolicy);  //丢弃并抛出异常
             executorService = new ThreadPoolExecutor(1,1,1L,TimeUnit.MINUTES,new ArrayBlockingQueue<1>, new ThreadPoolExecutor.DiscardPolicy); //丢弃不抛出异常
             executorService = new ThreadPoolExecutor(1,1,1L,TimeUnit.MINUTES,new ArrayBlockingQueue<1>, new ThreadPoolExecutor.DiscardOldestPolicy); //丢弃队列最前面的任务,然后重新尝试执行任务。
             executorService = new ThreadPoolExecutor(1,1,1L,TimeUnit.MINUTES,new ArrayBlockingQueue<1>, new ThreadPoolExecutor.DiscardPolicy); //由调用线程处理任务

        3.10 空对象模式 Null Object:

          原理:Null对象不是检查空值,而是反应一个不做任何动作的关系。这样的null对象也可以在数据不可用的时候提供默认的行为。

          举例:java.util.Collections.EMPTY_LIST;

     源码走读: @SuppressWarnings("unchecked")
              public static final List EMPTY_LIST = new EmptyList<>();

        3.11 模板模式 Template:

          原理:主要解决一些方法通用,却在每一个子类都重写了这一方法。将这些通用的方法抽象出来。

          举例:java.util.Coolections;  org.springframework.jms.core.JmsTemplate;

        public static <T extends Comparable<? super T>> void sort(List<T> list) {
            Object[] a = list.toArray();
            Arrays.sort(a);
            ListIterator<T> i = list.listIterator();
            for (int j=0; j<a.length; j++) {
                i.next();
                i.set((T)a[j]);
            }
        }

        3.12 访问者模式 Visitor:

          原理:主要将数据结构与数据操作分离,稳定的数据结构和以便的操作耦合问题。

          举例:java.nio.file.FileVisitor; // 通过Files.walkFileTree方法实现对文件树中每一个文件的访问。

    // 使用FileVisitor对目录进行遍历
            Files.walkFileTree(Paths.get("d:", "workspace"), new SimpleFileVisitor<Path>() {
    
                // 在访问子目录前触发该方法
                @Override
                public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                    System.out.println("正在访问" + dir + "目录");
                    return FileVisitResult.CONTINUE;
                }
    
                // 在访问文件时触发该方法
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                    System.out.println("正在访问" + file + "文件");
                    if (file.endsWith("FilesTest.java")) {
                        System.out.println("------已找到FilesTest.java,文件内容-----");
                        List<String> list = Files.readAllLines(file);
                        // 打印出文件的内容
                        System.out.println(list);
                        return FileVisitResult.TERMINATE;
                    }
                    return FileVisitResult.CONTINUE;
                }
    
                // 在访问失败时触发该方法
                @Override
                public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
                    // 写一些具体的业务逻辑
                    return super.visitFileFailed(file, exc);
                }
    
                // 在访问目录之后触发该方法
                @Override
                public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                    // 写一些具体的业务逻辑
                    return super.postVisitDirectory(dir, exc);
                }
            });
  • 相关阅读:
    MySql基础教程(三)——查询训练
    MySql基础教程(二)
    MySql基础教程(一)
    解决Eclipse闪退问题的方法总结
    MySQL图形工具 MySQL GUI Tools的安装使用方法
    MySql5.6版修改用户登录密码
    Windows下MySQL解压版的配置
    js 数组容易弄混的那些方法
    如何使CSS--better(系列二)
    如何使CSS--better(系列一)
  • 原文地址:https://www.cnblogs.com/zhitianji/p/9713822.html
Copyright © 2011-2022 走看看