当前位置: 首页 > article >正文

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

原理和实现

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

具体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;
        }

    }
}

复用

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;

}

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++;
    }

拓展

java servlet

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

小结

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


http://www.kler.cn/news/135557.html

相关文章:

  • 解析Spring Boot中的CommandLineRunner和ApplicationRunner:用法、区别和适用场景详解
  • CISP全真模式测试题(二)
  • VSCode使用
  • 基于Vue+SpringBoot的超市账单管理系统 开源项目
  • CentOS 7.9 安装 epel-release
  • cobol基本语法
  • k8s-部署Redis-cluster(TLS)
  • 【React】React 基础
  • 基础算法:高精度加法
  • C语言之深入指针及qsort函数(五)(详解介绍)
  • 微信小程序内嵌h5页面,实现动态设置顶部标题的功能
  • ArkTS - HarmonyOS服务卡片(创建)
  • CISP模拟试题(一)
  • uniapp+vue+Springboot 公司网站0~1搭建 前端前期设计篇
  • 串行通信中的同步方式(Synchronous)与异步方式(Asynchronous)stty -F设置波特率
  • “移动机器人课程群实践创新的困境与突围”素材
  • 动态页面调研及设计方案
  • 【Java 进阶篇】Ajax 实现——原生JS方式
  • 文件传输客户端 SecureFX mac中文版支持多种协议
  • 归并排序详解:递归实现+非递归实现(图文详解+代码)
  • 设计模式-组合模式-笔记
  • 应试教育导致学生迷信标准答案惯性导致思维僵化-移动机器人
  • Android描边外框stroke边线、rotate旋转、circle圆形图的简洁通用方案,基于Glide与ShapeableImageView,Kotlin
  • 【双指针】快乐数
  • Wireshark TS | 应用传输缓慢问题
  • 【运维篇】Redis 性能测试工具实践
  • 米家竞品分析
  • OceanBase 4.2.1 LTS 发版 | 一体化数据库首个长期支持版本
  • 数据结构与算法之美学习笔记:22 | 哈希算法(下):哈希算法在分布式系统中有哪些应用?
  • 面向开发者的Android