文章目录
简单工厂
定义 :由一个工厂对象决定创建出哪一种产品类的实例
类型 :创建型,但不属于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类图 :
说明 :可以看到三个实例工厂对应生产三个类的实例,Test测试类中要使用哪个实例,直接找对象的工厂实例get即可。
JDK源码中使用例子 :java.util.Collection#iterator,工厂接口方法
什么是产品族
图示 :
说明 :
每一行就是一个产品族,比如美的,方形表示美的冰箱,圆形表示美的空调,椭圆形表示美的热水器
每一列是一个产品等级结构,比如第一行的圆形表示美的空调,第二行圆形表示格力空调,第三行圆形表示海尔空调