From the documentation of Condition:
Condition factors out the Object monitor methods (wait, notify and notifyAll) into distinct objects to give the effect of having multiple wait-sets per object, by combining them with the use of arbitrary Lock implementations. Where a Lock replaces the use of synchronized methods and statements, a Condition replaces the use of the Object monitor methods.
Conditions (also known as condition queues or condition variables) provide a means for one thread to suspend execution (to "wait") until notified by another thread that some state condition may now be true. Because access to this shared state information occurs in different threads, it must be protected, so a lock of some form is associated with the condition. The key property that waiting for a condition provides is that it atomically releases the associated lock and suspends the current thread, just like Object.wait.
A Condition instance is intrinsically bound to a lock. To obtain a Condition instance for a particular Lock instance use its newCondition() method. 
As explained, a Condition instance must be associated with a Lock instance1. Having Lock function as a factory for creating instances of Condition makes perfect sense with that in mind as it implies the relationship between the two. Another way this relationship could have been enforced is to give Condition a constructor which accepts a Lock instance, but since Condition is also an interface it cannot declare constructors. I'm also of the opinion that a no-argument factory method is more user friendly in this case anyway.
Note: If it's not already clear, the ReentrantLock class is an implementation of the Lock interface and the ConditionObject class is an implementation of the Condition interface.
The other problem with attempting to use ConditionObject directly is that it's an inner class (i.e. non-static nested class) of AbstractQueuedSynchronizer2. This means you would need an instance of the latter class in order to create an instance of the former class. However, the implementation of AbstractQueuedSynchronizer used by ReentrantLock is an implementation detail and not exposed to the public. In other words, you have no way to call the constructor of ConditionObject which means the only way to create an instance is via newCondition().
To recap, there's at least three reasons why a factory method is used to create Condition objects:
- It makes the relationship between LockandConditionclear.
- With both LockandConditionbeing interfaces, you need a way to associate aConditionwith aLockwithout knowing about the implementations. Otherwise it would not be possible to "program to an interface".
- Due to ConditionObjectbeing an inner class it cannot be instantiated directly—at least, not by code which doesn't have access to an instance of the enclosing class.
1. The methods of Condition only make sense in the context of owning a Lock. Just like how a thread must be synchronized on an object before it can legally invoke that object's monitor methods (i.e. wait/notify), a thread must own the associated Lock before it can legally invoke the methods of the Condition (i.e. await/signal).
2. There's also AbstractQueuedLongSynchronizer which declares its own ConditionObject inner class. While the class has the same name as the one declared by AbstractQueuedSynchronizer, the two are actually separate classes.