private PathChildrenCache pathChildrenCache(String path, ZooKeeperDiscoverySpec spec) {
        final PathChildrenCache pathChildrenCache = new PathChildrenCache(client, path, true);
        pathChildrenCache.getListenable().addListener((c, event) -> {
            switch (event.getType()) {
                case CHILD_ADDED:
                    final Endpoint addedEndpoint = endpoint(spec, event);
                    if (addedEndpoint != null) {
                        addEndpoint(addedEndpoint);
                    }
                    break;
                case CHILD_REMOVED:
                    final Endpoint removedEndpoint = endpoint(spec, event);
                    if (removedEndpoint != null) {
                        removeEndpoint(removedEndpoint);
                    }
                    break;
                default:
                    break;
            }
        });
        return pathChildrenCache;
    }
Returns a new {@link ZooKeeperEndpointGroupBuilder} created with the specified {@link CuratorFramework}
and ZNode path. Note that the specified {@link CuratorFramework} will not be destroyed when
the {@link ZooKeeperEndpointGroup} built by the returned builder is closed.

@param client the curator framework instance
@param znodePath the ZooKeeper node to register
@param spec the {@link ZooKeeperDiscoverySpec} to find and decode the registered instances
zookeeper3/src/main/java/com/linecorp/armeria/client/zookeeper/ZooKeeperEndpointGroup.java