1. Factory method mode
1.1 ordinary factory mode (mode I)
Establish a factory class to create instances of some classes that implement the same interface. First look at the diagram below:
An example: sending email and SMS
First, create a common interface between the two:
public interface Sender { public void Send(); }
Secondly, create an implementation class:
public class MailSender implements Sender { @Override public void Send() { System.out.println("this is mailsender!"); } } public class SmsSender implements Sender { @Override public void Send() { System.out.println("this is sms sender!"); } }
Finally, plant construction:
public class SendFactory { public Sender produce(String type) { if ("mail".equals(type)) { return new MailSender(); } else if ("sms".equals(type)) { return new SmsSender(); } else { System.out.println("Please enter the correct type!"); return null; } } }
Test:
public class FactoryTest { public static void main(String[] args) { SendFactory factory = new SendFactory(); Sender sender = factory.produce("sms"); sender.Send(); } }
Output results:
this is sms sender!
1.2 multiple plant method mode (mode 2)
The improvement of the ordinary factory method mode has the following two disadvantages (including but not limited to):
- If the string passed is wrong, the object cannot be created correctly
- If each type is added, do I have to modify the if else of the produce method? Isn't this against our opening and closing principle?
The multiple factory method pattern provides multiple factory methods to create objects respectively. Diagram:
Modify the above code and change the SendFactory class as follows:
public class SendFactory { public Sender produceMail(){ return new MailSender(); } public Sender produceSms(){ return new SmsSender(); } }
Test:
public class FactoryTest { public static void main(String[] args) { SendFactory factory = new SendFactory(); Sender sender = factory.produceMail(); sender.Send(); } }
Output results:
this is mailsender!
1.3 static factory method mode (mode 3)
Set the methods in the above multiple factory method patterns as static. You can call them directly without creating an instance.
public class SendFactory { public static Sender produceMail(){ return new MailSender(); } public static Sender produceSms(){ return new SmsSender(); } }
Test:
public class FactoryTest { public static void main(String[] args) { Sender sender = SendFactory.produceMail(); sender.Send(); } }
Output results:
this is mailsender!
2. Abstract factory mode
A problem with the factory method pattern is that the creation of classes depends on factory classes, that is, if you want to expand the program, you must modify the factory class, which violates the closure principle. Therefore, from the design point of view, there are certain problems. How to solve them? The abstract factory pattern is used to create multiple factory classes. In this way, once new functions need to be added, new factory classes can be added directly without modifying the previous code. Because the abstract factory is not easy to understand, let's look at the diagram first, and then compare it with the code, which is easier to understand.
Interface class:
public interface Sender { public void Send(); }
Two implementation classes:
public class MailSender implements Sender { @Override public void Send() { System.out.println("this is mailsender!"); } } public class SmsSender implements Sender { @Override public void Send() { System.out.println("this is sms sender!"); } }
Two factory classes:
public class SendMailFactory implements Provider { @Override public Sender produce(){ return new MailSender(); } } public class SendSmsFactory implements Provider{ @Override public Sender produce() { return new SmsSender(); } }
Another factory class interface is provided:
public interface Provider { public Sender produce(); }
Test:
public class Test { public static void main(String[] args) { Provider provider = new SendMailFactory(); Sender sender = provider.produce(); sender.Send(); } }
In fact, the advantage of this mode is that if you want to add a function: sending timely information, you only need to make an implementation class to implement the Sender interface and a factory class to implement the Provider interface. It's OK without changing the ready-made code. In this way, the expansibility is better!