一、简单工厂
一句话总结:根据工厂类中方法传入的参数返回所需的对象。
定义 :由一个工厂对象决定创建出哪一种产品类的实例
类型 :创建型,但不属于GOF(Gang of Four,四人组)23种设计模式使用场景 :
工厂类负责创建的对象比较少
客户端(应用层)只知道传入工厂类的参数,对于如何创建对象逻辑不关心 优点 :只需要传入一个正确的参数,就可以获取你所需要的对象而无需知道其创建的细节缺点 :工厂类的职责相对过重,增加新的产品需要修改工厂类的判断逻辑,违背开闭原则Coding :
public abstract class Video {
public abstract void produce ( ) ;
}
public class JavaVideo extends Video {
@Override
public void produce ( ) {
System. out. println ( "Java。。。" ) ;
}
}
public class PythonVideo extends Video {
@Override
public void produce ( ) {
System. out. println ( "Python。。。" ) ;
}
}
public class VideoFactory {
public Video getVideo ( String type) {
if ( "java" . equalsIgnoreCase ( type) ) {
return new JavaVideo ( ) ;
} else if ( "python" . equalsIgnoreCase ( type) ) {
return new PythonVideo ( ) ;
}
return null;
}
}
public class Test {
public static void main ( String[ ] args) {
VideoFactory videoFactory = new VideoFactory ( ) ;
Video video = videoFactory. getVideo ( "java" ) ;
if ( video == null) {
return ;
}
video. produce ( ) ;
}
}
== == == == == == == == == == == == == == == == == == 控制台输出 == == == == == == == == == == == == == == == == == == == =
Java。。。
UML类图 : 说明 :看UML图就非常清晰了,Test测试类只创建Video工厂,而Java和Python由工厂创建,Test通过工厂获取Java或Python实例即可。缺点也很明显,如果再来个Go语言类,就需要去修改工厂,每加一个都要去修改,这就会带来风险,也不符合开闭原则。反射方式改造 :
public class 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源码中使用例子 :java.util.Calendar#createCalendar
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 ;
}
}
}
二、工厂方法
一句话总结:定义一个工厂接口(或抽象类),实现这个工厂接口的工厂类去决定实例化哪个类,一个工厂类只实例化一个类。
定义 :定义一个创建对象的接口,让实现这个接口的类来决定实例化哪个类,工厂方法让类的实例化推迟到子类中进行
类型 :创建型使用场景 :
创建对象需要大量重复的代码
客户端(应用层)不依赖于产品类实例如何被创建、实现等细节 一个类通过其子类类指定创建哪个对象 优点 :
用户只需要关心产品对应的工厂,无需关心创建细节 加入新产品符合开闭原则,提高可扩展性 缺点 :
类的个数容易过多,增加复杂度 增加了系统的抽象性和理解难度 Coding :
public abstract class Video {
public abstract void produce ( ) ;
}
public class FEVideo extends Video {
@Override
public void produce ( ) {
System. out. println ( "FE。。。" ) ;
}
}
public class JavaVideo extends Video {
@Override
public void produce ( ) {
System. out. println ( "Java。。。" ) ;
}
}
public class PythonVideo extends Video {
@Override
public void produce ( ) {
System. out. println ( "Python。。。" ) ;
}
}
public abstract class VideoFactory {
public abstract Video getVideo ( ) ;
}
public class PythonVideoFactory extends VideoFactory {
@Override
public Video getVideo ( ) {
return new PythonVideo ( ) ;
}
}
public class JavaVideoFactory extends VideoFactory {
@Override
public Video getVideo ( ) {
return new JavaVideo ( ) ;
}
}
public class FEVideoFactory extends VideoFactory {
@Override
public Video getVideo ( ) {
return new FEVideo ( ) ;
}
}
public class Test {
public static void main ( String[ ] args) {
VideoFactory videoFactory = new PythonVideoFactory ( ) ;
VideoFactory videoFactory2 = new JavaVideoFactory ( ) ;
VideoFactory videoFactory3 = new FEVideoFactory ( ) ;
Video video = videoFactory. getVideo ( ) ;
video. produce ( ) ;
}
}
== == == == == == == == == == == == == == == == == == 控制台输出 == == == == == == == == == == == == == == == == == == == =
Java。。。
UML类图 : 说明 :可以看到三个实例工厂对应生产三个类的实例,Test测试类中要使用哪个实例,直接找对象的工厂实例get即可。JDK源码中使用例子 :java.util.Collection#iterator,工厂接口方法
三、抽象工厂
一句话总结:定义一个抽象工厂接口,包含一系列创建的接口方法,这些方法的返回是一个接口,意味着一个接口方法可以生产实现该接口的所有类对象
定义 :抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口
,无需指定他们具体的类类型 :创建型使用场景 :
客户端(应用层)不依赖于产品类实例如何被创建、实现等细节 强调一系列相关产品对象(属于同一产品族,产品族概念后面有解释)一起使用创建对象需要大量重复的代码
提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现 优点 :
具体产品在应用层代码隔离,无需关心创建细节 将一个系列的产品族统一到一起创建 缺点 :
规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口 增加了系统的抽象性和理解难度 Coding :
public abstract class Article {
public abstract void produce ( ) ;
}
public class JavaArticle extends Article {
@Override
public void produce ( ) {
System. out. println ( "Java文章。。。" ) ;
}
}
public class PythonArticle extends Article {
@Override
public void produce ( ) {
System. out. println ( "Python文章。。。" ) ;
}
}
public abstract class Video {
public abstract void produce ( ) ;
}
public class JavaVideo extends Video {
@Override
public void produce ( ) {
System. out. println ( "Java。。。" ) ;
}
}
public class PythonVideo extends Video {
@Override
public void produce ( ) {
System. out. println ( "Python。。。" ) ;
}
}
public interface CourseFactory {
Video getVideo ( ) ;
Article getArticle ( ) ;
}
public class JavaCourseFactory implements CourseFactory {
@Override
public Video getVideo ( ) {
return new JavaVideo ( ) ;
}
@Override
public Article getArticle ( ) {
return new JavaArticle ( ) ;
}
}
public class PythonCourseFactory implements CourseFactory {
@Override
public Video getVideo ( ) {
return new PythonVideo ( ) ;
}
@Override
public Article getArticle ( ) {
return new PythonArticle ( ) ;
}
}
public class Test {
public static void main ( String[ ] args) {
CourseFactory courseFactory = new JavaCourseFactory ( ) ;
Video video = courseFactory. getVideo ( ) ;
Article article = courseFactory. getArticle ( ) ;
video. produce ( ) ;
article. produce ( ) ;
}
}
== == == == == == == == == == == == == == == == == == 控制台输出 == == == == == == == == == == == == == == == == == == == =
Java视频。。。
Java文章。。。
UML类图 : 说明 :关键在于工厂接口 CourseFactory
,定义了两个接口方法 getVideo()、getArticle()
,他们的返回都不具体是哪个实例,而是抽象类(或者接口)。JDK源码中使用例子 :java.util.Collection#iterator,工厂接口方法
四、什么是产品族
图示 : 说明 :
每一行就是一个产品族,比如美的,方形表示美的冰箱,圆形表示美的空调,椭圆形表示美的热水器 每一列是一个产品等级结构,比如第一行的圆形表示美的空调,第二行圆形表示格力空调,第三行圆形表示海尔空调