The Factory pattern isn't inherently a violator of OCP.
It depends on how you take the behavior of Complex further.
If Complex is required to support the production of new types of Complex object, and you choose to modify Complex by adding new fromX methods are added to support them, then this means that Complex becomes a violator of the OCP because Complex must be re-opened for modification:
class Complex
{
public static Complex fromCartesian(double real, double imag) {
return new Complex(real, imag);
}
public static Complex fromPolar(double modulus, double angle) {
return new Complex(modulus * cos(angle), modulus * sin(angle));
}
//class opened for modification
public static Complex fromOtherMeans(String x , String y) {
return new Complex(x, y);
}
}
You could push this problem down into a text file or properties file of some sort in order to absolve yourself of having to change the java class, but it doesn't prevent you from having to write extra logic in this area of the solution in order to support new types of Complex.
Depending on the usage of Complex in your design (how are the various types different? How are you using them?), there are some alternative options which may apply well.
One such OCP friendly alternative is to subclass Complex to provide the additional factory methods. A subclass is the simplest illustration of how Complex is extended but not modified.
Another OCP friendly alternative to altering Complex in this case is the Decorator pattern. Continuously decorating Complex with the ability to create new variants of Complex respects the OCP because Complex is not modified but is extended by wrapping it with new functionality.
A third alternative might be to alter the structure of Complex so that its calculation is supplied by composition. This would open up to you the opportunity to use the Strategy pattern to diferentiate between the different behaviours of Complex.
The thing about the Factory pattern is that it helps context code respect OCP. One might employ one of the techniques above in order to stay on the right side of the OCP with their Factory class, but your colleagues are likely to take one look at the object graph, question the wisdom of having an object graph over a single Factory, and simplify it back into one Factory, which brings you back to to the first example.
In such cases, rather than trying to bend your implementation of the Factory pattern to respect the SOLID principles, consider why you're using it at all.