Detailed factory mode (1)-simple factory mode

1. The historical origin of the factory model

In real life, we all know that primitive society is self-sufficient (no factory), small farming society (simple factory, folk wine shop), industrial revolution assembly line (factory method, self-produced and self-sold), modern industrial chain foundry (abstract) Factory, Foxconn)

2. Simple factory model

The simple factory pattern (Simple Factory Pattern) refers to an instance of which product class is created by a factory object, but it does not belong to GOF, 23 design patterns. Reference materials
Simple factory is suitable for scenarios where the factory class is responsible for creating fewer objects, and the client only needs to pass in the parameters of the factory class, and there is no need to care about the logic of how to create the objects.

First, we can define a course standard ICourse interface

public interface ICourse {
    
    
/** 录制视频 */
	public void record();
}

Create a Java course implementation JavaCourse class:

public class JavaCourse implements ICourse {
    
    
  public void record() {
    
    
 	 System.out.println("录制 Java 课程");
  }
}

Create the CourseFactory factory class:

public class CourseFactory {
    
    
	public ICourse create(String name){
    
    
		if("java".equals(name)){
    
    
			return new JavaCourse();
		}else if("python".equals(name)){
    
    
			return new PythonCourse();
		}else {
    
    
			return null;
		}
	}
}

Modify the client calling code:

public class SimpleFactoryTest {
    
    
	public static void main(String[] args) {
    
    
		CourseFactory factory = new CourseFactory();
		factory.create("java");
	}
}

Of course, for the convenience of calling, we can change the create() of the factory to a static method. Let’s take a look:
Insert picture description here
client-side calling is simple, but if our business continues to expand and we need to add front-end courses, then create() in the factory It is necessary to modify the code logic every time according to the richness of the product chain. Does not conform to the principle of opening and closing. Therefore, we can continue to optimize the simple factory, and we can use reflection technology:

public class CourseFactory {
    
    
	public ICourse create(String className){
    
    
		try {
    
    
			if (!(null == className || "".equals(className))) {
    
    
				return (ICourse) Class.forName(className).newInstance();
            }
        }catch (Exception e){
    
    
        	e.printStackTrace();
		}
		return null;
	}
}

Modify the client calling code:

public static void main(String[] args) {
    
    
	CourseFactory factory = new CourseFactory();
	ICourse course = factory.create("com.gupaoedu.vip.pattern.factory.simple factory.JavaCourse");
	course.record();
}

After optimization, the product is continuously enriched without modifying the code in CourseFactory. However, there is a problem that the method parameter is a string, the controllability needs to be improved, and a mandatory transformation is required. Let's modify the code again:

public ICourse create(Class<? extends ICourse> clazz){
    
    
	try {
    
    
		if (null != clazz) {
    
    
		return clazz.newInstance();
		}
	}catch (Exception e){
    
    
		e.printStackTrace();
	}
	return null;
}

Optimize the client code:

public static void main(String[] args) {
    
    
	CourseFactory factory = new CourseFactory();
	ICourse course = factory.create(JavaCourse.class);
	course.record();
}

Look at the class diagram again: the
Insert picture description here
simple factory pattern is also ubiquitous in the JDK source code. Now let's take an example, such as the Calendar class. Look at the Calendar.getInstance() method. The following is the specific creation class of Calendar:

private static Calendar createCalendar(TimeZone zone, Locale aLocale)
{
    
    
	CalendarProvider provider =
		LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale).getCalendarProvider();
		
	if (provider != null) {
    
    
		try {
    
    
			return provider.getInstance(zone, aLocale);
		} catch (IllegalArgumentException iae) {
    
    
			// fall back to the default instantiation
		}
	}
	
	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 no known calendar type is explicitly specified, 	
			// perform the traditional way to create a Calendar: 
			// create a BuddhistCalendar for th_TH locale, 				
			// a JapaneseImperialCalendar for ja_JP_JP locale, or
			// a GregorianCalendar for any other locales. 			
			// NOTE: The language, country and variant strings are interned.
			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 = new GregorianCalendar(zone, aLocale);
			}
		}
			return cal;
}

There is also a logback that everyone often uses. We can see that there are multiple overloaded methods in the LoggerFactory getLogger():

public static Logger getLogger(String name) {
    
    
	ILoggerFactory iLoggerFactory = getILoggerFactory();
	return iLoggerFactory.getLogger(name);
}

public static Logger getLogger(Class clazz) {
    
    
	return getLogger(clazz.getName());
}

The simple factory also has its shortcomings: the responsibilities of the factory class are relatively heavy, and it is not easy to extend the overly complex product structure.

Guess you like

Origin blog.csdn.net/weixin_46822085/article/details/108837389