标签:coding sep jdk imp 开放 final 细节 xtend 参数
一、定义:由一个工厂对象决定创建出哪一种产品类的实例
二、类型:创建型,但不属于GOF23种设计模式
三、适用场景:
工厂类负责创建的对象比较少
客户端(应用层)只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心。
四、优点:
只需要传入一个正确的参数,就可以获取你所需要的对象,而无须知道其创建细节
五、缺点:
工厂类的职责相对过重,增加新的产品需要修改工厂类的判断逻辑,违背开闭原则
六、Coding
1.创建Video抽象类
public abstract class Video { public abstract void produce(); }
里面包含一个抽象方法 produce代表录制视频
2.创建JavaVideo类,继承Video抽象类
public class JavaVideo extends Video{ @Override public void produce() { System.out.println("录制Java视频"); } }
3. 创建AndroidVideo类,继承Video抽象类
public class AndroidVideo extends Video{ @Override public void produce() { System.out.println("录制Android视频"); } }
4. 创建工厂类
public class VideoFactory { public Video getVideo(String type){ if("java".equalsIgnoreCase(type)){ return new JavaVideo(); }else if("android".equalsIgnoreCase(type)){ return new AndroidVideo(); } return null; } }
5. 创建测试类或者应用类
public class Test { public static void main(String[] args) { VideoFactory videoFactory = new VideoFactory(); Video video = videoFactory.getVideo("java"); if(video == null){ return; } video.produce(); } }
6. UML图如下:
7. 缺点: 如果要增加Ios视频录制,则要修改工厂类的判断逻辑以及增加IosVideo类
这样违背开放闭合原则
改进方法: 将工厂类中通过字符创建实例的方法改为通过反射创建实例,这样增加IosVideo时,工厂类就不需要做修改
改进后的VideoFactory 类
public Video getVideo(Class c) { Video video = null; try { video = (Video) Class.forName(c.getName()).newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return video; }
测试类的调用方法
public class Test { public static void main(String[] args) { VideoFactory videoFactory = new VideoFactory(); Video video = videoFactory.getVideo(JavaVideo.class); if(video == null){ return; } video.produce(); } }
七、JDK源码中使用简单工厂模式的地方
1. Calendar类
public static Calendar getInstance(TimeZone zone, Locale aLocale) { return createCalendar(zone, aLocale); }
createCalendar方法
private static Calendar createCalendar(TimeZone zone, Locale aLocale) { Calendar cal = null; String caltype = aLocale.getUnicodeLocaleType("ca"); if (caltype == null) { // Calendar type is not specified. // If the specified locale is a Thai locale, // returns a BuddhistCalendar instance. if ("th".equals(aLocale.getLanguage()) && ("TH".equals(aLocale.getCountry()))) { cal = new BuddhistCalendar(zone, aLocale); } else { cal = new GregorianCalendar(zone, aLocale); } } else if (caltype.equals("japanese")) { cal = new JapaneseImperialCalendar(zone, aLocale); } else if (caltype.equals("buddhist")) { cal = new BuddhistCalendar(zone, aLocale); } else { // Unsupported calendar type. // Use Gregorian calendar as a fallback. cal = new GregorianCalendar(zone, aLocale); } return cal; }
根据caltype类型,创建对应的实例。
uml图
2. logback中ILoggerFactory.class中的getLogger方法
public final Logger getLogger(String name) { if(name == null) { throw new IllegalArgumentException("name argument cannot be null"); } else if("ROOT".equalsIgnoreCase(name)) { return this.root; } else { int i = 0; Logger logger = this.root; Logger childLogger = (Logger)this.loggerCache.get(name); if(childLogger != null) { return childLogger; } else { int h; do { h = LoggerNameUtil.getSeparatorIndexOf(name, i); String childName; if(h == -1) { childName = name; } else { childName = name.substring(0, h); } i = h + 1; synchronized(logger) { childLogger = logger.getChildByName(childName); if(childLogger == null) { childLogger = logger.createChildByName(childName); this.loggerCache.put(childName, childLogger); this.incSize(); } } logger = childLogger; } while(h != -1); return childLogger; } } }
根据name,获得哪一个log
标签:coding sep jdk imp 开放 final 细节 xtend 参数
原文地址:https://www.cnblogs.com/linlf03/p/9741060.html