• 【设计模式】聊聊模板模式


    原理和实现

    设计模式的原理和实现是比较简单的,难的是掌握具体的应用场景和解决什么问题。而模板模式是为来解决复用和拓展两个问题。
    模板模式在一个方法中定义好一个算法框架,然后将某些步骤推迟到子类中实现,子类可以在不修改父类流程的时候,实现自己的特有逻辑。

    具体code如下。ZkLock定义顶层接口设计,ZkAbstractTemplateLock 实现了基础功能,但是具体的wait和try的流程是固定在ZKlock抽象类中,子类只能根据自己的特性实现对应的方法。

    
    public interface ZkLock {
        /***
         * 获取锁
         */
        public void zkLock();
    
        /***
         * 释放锁
         */
        public void zkUnLock();
    
    }
    
    
    public abstract class ZkAbstractTemplateLock implements ZkLock {
    
        private static final String ZKSERVER = "192.168.58.138:2181";
        private static final int TIME_OUT = 45 * 100;
    
        public static final String zkLockPath = "/zkLock";
        public static CountDownLatch countDownLatch = null;
    
        ZkClient zkClient =  new ZkClient(ZKSERVER,TIME_OUT);
    
        @Override
        public void zkLock() {
            //模板设计方法 抽象定义在父类中,具体实现由子类来实现
            if (tryLock()){
                System.out.println(Thread.currentThread().getName()+"\t 拿到锁");
            }else {
                waitLock();
                zkLock();
            }
        }
    
        //将公共的代码抽取到父类中
        public abstract void waitLock();
    
        /***
         * 尝试获取锁
         * @return
         */
        public abstract boolean tryLock();
    
        @Override
        public void zkUnLock() {
            if(zkClient!=null){
                zkClient.close();//关闭客户端 node节点自动删除
            }
            System.out.println(Thread.currentThread().getName()+"\t 释放锁成功");
            System.out.println();
        }
    }
    
    
    public class ZkDistributedLock extends ZkAbstractTemplateLock {
    
        @Override
        public void waitLock() {
            IZkDataListener iZkDataListener = new IZkDataListener() {
                @Override
                public void handleDataChange(String s, Object o) throws Exception {
                }
    
                //数据被修改 监听Watch
                @Override
                public void handleDataDeleted(String s) throws Exception {
                    //如果节点数据删除了 那么countDownLatch减一
                    countDownLatch.countDown();
                }
            };
    
            //在某一个节点上监听事件
            zkClient.subscribeDataChanges(zkLockPath,iZkDataListener);
    
            //当不为null
            if (zkClient.exists(zkLockPath)){
                countDownLatch = new CountDownLatch(1);//计数1 为0返回
                try {
                    //一旦节点被删除 触发事件就执行
                    countDownLatch.await();
                } catch (InterruptedException e) {
                    e.fillInStackTrace();
                }
            }
            //解除监听器
            zkClient.unsubscribeDataChanges(zkLockPath,iZkDataListener);
        }
    
        @Override
        public boolean tryLock() {
            try {
                zkClient.createEphemeral(zkLockPath);
                return true;
            }catch (Exception e){
                return false;
            }
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102

    复用

    java inputstream

    inputstream 定义了read的基础读取方法,但是也暴露了一个子类可以定制的抽象方法。

    public abstract class InputStream implements Closeable {
        public int read(byte b[], int off, int len) throws IOException {
            if (b == null) {
                throw new NullPointerException();
            } else if (off < 0 || len < 0 || len > b.length - off) {
                throw new IndexOutOfBoundsException();
            } else if (len == 0) {
                return 0;
            }
    
            int c = read();
            if (c == -1) {
                return -1;
            }
            b[off] = (byte)c;
    
            int i = 1;
            try {
                for (; i < len ; i++) {
                    c = read();
                    if (c == -1) {
                        break;
                    }
                    b[off + i] = (byte)c;
                }
            } catch (IOException ee) {
            }
            return i;
        }
    
        public abstract int read() throws IOException;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    java abstractList

    abstract class AbstractList 定义了addAll() , 但是留除了一个拓展点给子类,如果子类不实现的话,不能使用。

    
        public boolean addAll(int index, Collection<? extends E> c) {
            rangeCheckForAdd(index);
            boolean modified = false;
            for (E e : c) {
                add(index++, e);
                modified = true;
            }
            return modified;
        }
        	
        public void add(int index, E element) {
            throw new UnsupportedOperationException();
        }
    
        //arraylist实现了自己的 add
        public void add(int index, E element) {
            rangeCheckForAdd(index);
    
            ensureCapacityInternal(size + 1);  // Increments modCount!!
            System.arraycopy(elementData, index, elementData, index + 1,
                             size - index);
            elementData[index] = element;
            size++;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    拓展

    java servlet

    在这里插入图片描述
    拓展点这里其实是指框架的拓展点,即用户在不修改框架源码的时候,只需要按照框架提高的类进行拓展就可以实现自己的业务逻辑。

    小结

    模板模式的本质定义一个框架流程,具体的拓展点可以子类进行实现。具体的功能是复用和拓展,复用是指的是,所有的子类可以复用父类中提供的模板方法的代码,拓展是框架通过模板模式提供功能拓展点,用户不修改框架源码的情况下,基于拓展点就可以实现功能。

  • 相关阅读:
    【HDLBits 刷题 6】Circuits(2)Sequential Logic---Latches and Filp Flops
    Jvm系列第一期——Java类加载机制
    C语言学习之原码、反码、补码
    STM32HAL库开发
    手把手教你Python如何抓包~【异常详细版】
    目标检测算法之损失函数(IOU、GIOU、DIOU、CIOU、EIOU)
    Typescript-----接口
    软件测试中bug修正后测试就结束了吗?
    循序渐进了解如何使用JSR303进接口数据校验
    python图形界面化编程GUI(六)坦克大战(二)
  • 原文地址:https://blog.csdn.net/jia970426/article/details/134496333