class PooledStringEncryptor implements StringEncryptor {

    private final int size;
    private final StringEncryptor[] pool;
    private final AtomicInteger roundRobin;

    /**
     * <p>Constructor for PooledStringEncryptor.</p>
     *
     * @param size a int
     * @param encryptorFactory a {@link java.util.function.Supplier} object
     */
    public PooledStringEncryptor(int size, Supplier<StringEncryptor> encryptorFactory) {
        this.size = size;
        this.pool = IntStream.range(0, this.size).boxed().map(v -> {
            StringEncryptor encryptor = encryptorFactory.get();
            if (encryptor instanceof ThreadSafeStringEncryptor) {
                return encryptor;
            }
            return new ThreadSafeStringEncryptor(encryptor);
        }).toArray(StringEncryptor[]::new);
        this.roundRobin = new AtomicInteger();
    }

    private <T> T robin(Function<StringEncryptor, T> producer) {<FILL_FUNCTION_BODY>}

    /** {@inheritDoc} */
    @Override
    public String encrypt(String message) {
        return robin(e -> e.encrypt(message));
    }

    /** {@inheritDoc} */
    @Override
    public String decrypt(String encryptedMessage) {
        return robin(e -> e.decrypt(encryptedMessage));
    }

    public static class ThreadSafeStringEncryptor implements StringEncryptor {
        private final StringEncryptor delegate;

        public ThreadSafeStringEncryptor(StringEncryptor delegate) {
            this.delegate = delegate;
        }

        @Override
        public synchronized String encrypt(String message) {
            return delegate.encrypt(message);
        }

        @Override
        public synchronized String decrypt(String encryptedMessage) {
            return delegate.decrypt(encryptedMessage);
        }
    }
}

        int position = this.roundRobin.getAndUpdate(value ->  (value + 1) % this.size);
        return producer.apply(this.pool[position]);

    
<no_super_class>