public static <E> BlockingQueue<E> newBlockingQueue(ConcurrentQueueSpec qs,
            Class<? extends TakeStrategy> takeStratClass, Class<? extends PutStrategy> putStratClass) {
        // Check if strategies are compatible with QueueSpec
        boolean isTakeStratOK = false;
        boolean isPutStratOK = false;
        try {
            isTakeStratOK = takeStratClass.newInstance().supportsSpec(qs);
            isPutStratOK = putStratClass.newInstance().supportsSpec(qs);
        } catch (IllegalAccessException e) {
            throw new IllegalArgumentException("Error instantiating strategy");
        } catch (InstantiationException e) {
            throw new IllegalArgumentException("Error instantiating strategy");
        }

        if (!isTakeStratOK) {
            throw new IllegalArgumentException("The take strategy is not compatible with the Queue Specs");
        }
        if (!isPutStratOK) {
            throw new IllegalArgumentException("The put strategy is not compatible with the Queue Specs");
        }

        if (qs.isBounded()) {
            // SPSC
            if (qs.isSpsc()) {
                return getBlockingQueueFrom(SpscArrayQueue.class, takeStratClass, putStratClass, qs.capacity);
            }
            // MPSC
            else if (qs.isMpsc()) {
                if (qs.ordering != Ordering.NONE) {
                    return getBlockingQueueFrom(MpscArrayQueue.class, takeStratClass, putStratClass,
                            qs.capacity);
                } else {
                    return getBlockingQueueFrom(MpscCompoundQueue.class, takeStratClass, putStratClass,
                            qs.capacity);
                }
            }
            // SPMC
            else if (qs.isSpmc()) {
                return getBlockingQueueFrom(SpmcArrayQueue.class, takeStratClass, putStratClass, qs.capacity);
            }
            // MPMC
            else if (qs.isMpmc()) {
                return getBlockingQueueFrom(MpmcArrayQueue.class, takeStratClass, putStratClass, qs.capacity);
            }

            // Default bounded blocking
            return new ArrayBlockingQueue<E>(qs.capacity);
        } else {
            // SPSC
            if (qs.isSpsc()) {
                return getBlockingQueueFrom(SpscLinkedQueue.class, takeStratClass, putStratClass, -1);
            }
            // MPSC
            else if (qs.isMpsc()) {
                    return getBlockingQueueFrom(MpscLinkedQueue.class, takeStratClass, putStratClass, -1);
            }

            // Default unbounded blocking : CLQ based
            return getBlockingQueueFrom(ConcurrentLinkedQueue.class, takeStratClass, putStratClass, -1);
        }

    }
The queue factory produces {@link java.util.Queue} instances based on a best fit to the {@link ConcurrentQueueSpec}.
This allows minimal dependencies between user code and the queue implementations and gives users a way to express
their requirements on a higher level.

@author nitsanw
jctools-experimental/src/main/java/org/jctools/queues/blocking/BlockingQueueFactory.java