Simple Factory model
Definition of factory pattern: Define a factory interface to create product objects, deferring the actual creation of product objects to concrete subfactory classes. This satisfies the “create and use separation” characteristic required in the creative pattern.
According to the actual business scenarios, there are three different implementation modes of factory mode, namely simple factory mode, factory method mode and abstract factory mode. Here are a few design patterns.
Simple Factory Pattern: Defines a Factory class that can return instances of different classes depending on the parameters. The created instances usually have a common parent class.
Because the methods used to create instances in the simple Factory pattern are static methods, the simple Factory pattern is also known as the static Factory Method pattern. It belongs to the class-creation pattern, but not to the GOF23 design pattern
role
-
SimpleFactory: is the core of the SimpleFactory pattern and is responsible for implementing the internal logic that creates all instances. The method of creating a product class for a factory class can be called directly from the outside world to create the desired product object
-
Abstract Product: Is the parent of all objects created by a simple factory and is responsible for describing the common interface shared by all instances.
-
Concrete Products: Are the creation targets of the simple factory pattern.
Code case
- Abstract product
public abstract class Mobile {
/** * produces mobile phones */
public abstract void produce(a);
}
Copy the code
- Concrete product Concrete implementation of an abstract product
public class Iphone extends Mobile {
@Override
public void produce(a) {
System.out.println("apple iphone mobile"); }}public class Samsung extends Mobile{
@Override
public void produce(a) {
System.out.println("samsung Galaxy mobile"); }}Copy the code
- Simple factory
public class SimpileFactory {
public static Mobile getMobile(String type){
if (type.equals("iphone")) {
return new Iphone();
}else if (type.equals("samsung")) {
return new Samsung();
}
return null;
}
public static Mobile getMobileForRelect(@SuppressWarnings("rawtypes") Class clazz) {
try {
return (Mobile)Class.forName(clazz.getName()).newInstance();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null; }}Copy the code
- Use the client
public class Client {
public static void main(String[] args) {
Mobile mobile = SimpileFactory.getMobile("iphone"); mobile.produce(); }}Copy the code
The results
apple iphone mobile
Copy the code
Case chart
The client generates different brands of phones by passing the phone type to the factory method. Here we can also pass the specific type by reflection to get the phone object instance.
public static Mobile getMobileForRelect(@SuppressWarnings("rawtypes") Class clazz) {
try {
return (Mobile)Class.forName(clazz.getName()).newInstance();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
Copy the code
- The client obtains objects by reflection
public static void main(String[] args) {
Mobile mobile2 = SimpileFactory.getMobileForRelect(Samsung.class);
mobile2.produce();
}
Copy the code
Execution Result:
samsung Galaxy mobile
Copy the code
Either way, we just call the factory method to get the object we need. If we add a phone type, if we add Huawei phones, then the way our factory obtains objects by type still needs to be changed, which violates the “on/off principle”. For the user, no matter how many clients there are, there is no need to change the code, just pass in the new type and get the new object.
The advantages and disadvantages
Advantages:
- The factory class contains the logical judgment necessary to decide which product instance to create and when;
- The client can be exempted from the responsibility of directly creating product objects, and it is very convenient to create corresponding products.
- Clear distinction between factory and product responsibilities The client does not need to know the class name of the specific product being created, just the parameters.
- Configuration files can also be introduced to replace and add new concrete product classes without modifying the client code
Disadvantages:
- The simple factory mode has a single factory class, which is responsible for the creation of all products. The responsibility is too heavy. Once an exception occurs, the whole system will be affected. And the factory class code will be very bloated, against the principle of high aggregation.
- Using the simple factory pattern increases the number of classes in the system (introducing new factory classes), increasing the complexity and difficulty of understanding the system
- It is difficult to expand the system. Once a new product is added, the factory logic has to be modified. The logic may be too complicated when there are many product types
- The simple factory pattern uses the static factory approach, which prevents the factory roles from forming an inheritance-based hierarchy.
Application scenarios
- For a relatively small number of products, consider using the simple factory pattern.
- Clients using the simple factory pattern simply pass in the parameters of the factory class without worrying about the logic of how to create the object and can easily create the desired product.
Simple factory model typical application and source code analysis
The java.util package contains the Calendar class, which is an abstract class that gets the Calendar object (subclass object) via Calendar.getInstance(). The subclasses of abstract Calendar classes are BuddhistCalendar, JapaneseImperialCalendar and GregorianCalendar
public abstract class Calendar implements Serializable.Cloneable.Comparable<Calendar> {
public static Calendar getInstance(a)
{
return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
}
private static Calendar createCalendar(TimeZone zone, Locale aLocale)
{
/ /... slightly
Calendar cal = null;
if (aLocale.hasExtensions()) {
String caltype = aLocale.getUnicodeLocaleType("ca");
if(caltype ! =null) {
switch (caltype) {
case "buddhist":
cal = new BuddhistCalendar(zone, aLocale);
break;
case "japanese":
cal = new JapaneseImperialCalendar(zone, aLocale);
break;
case "gregory":
cal = new GregorianCalendar(zone, aLocale);
break; }}}if (cal == null) {
// ...
if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {
cal = new BuddhistCalendar(zone, aLocale);
} else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"
&& aLocale.getCountry() == "JP") {
cal = new JapaneseImperialCalendar(zone, aLocale);
} else {
cal = newGregorianCalendar(zone, aLocale); }}returncal; }}Copy the code
Truncated the main section, where the Calendar abstract class acts as both a factory and an abstract product, with the concrete product acting as a Calendar subclass.
✨✨ welcome 🔔 to subscribe to your wechat account for blog updates✨✨ Personal GitHub address