
package com.learn.design.pattern.creational.simplefactory;/*** 具体的视频的属性* 时常* 我们在类中就不描述了* 我们有一个生产视频的方法* 而这个生产视频应该是一个抽象方法* 例如JAVA课程的视频* 和Python课程的视频* 生产过程会有点不一样* * * @author Leon.Sun**/
public abstract class Video {/*** 所以我们现在写一个抽象方法* 这个时候我们的类也要是抽象类才可以* 因为拥有了抽象方法* 这个类必然是抽象类* * */public abstract void produce();}
package com.learn.design.pattern.creational.simplefactory;/*** 紧接着我们创建一个JAVA的视频实现类* 他继承Video这个抽象类* 同时实现produce方法* 现在我们填充这个实现* * * @author Leon.Sun**/
public class JavaVideo extends Video {@Overridepublic void produce() {System.out.println("录制Java课程视频");}
}
package com.learn.design.pattern.creational.simplefactory;/*** PythonVideo他也实现Vedio* 实现方法* * @author Leon.Sun**/
public class PythonVideo extends Video {@Overridepublic void produce() {System.out.println("录制Python课程视频");}
}
package com.learn.design.pattern.creational.simplefactory;/*** * @author Leon.Sun**/
public class VideoFactory {/*** 这里面我们使用Class* * 这个class* 就是包名* 后面是一个类* * * @param c* @return*/public Video getVideo(Class c){/*** 这里声明Video等于null* 后面会说明为什么要什么Video等于null* * */Video video = null;try {/*** c.getName()获取类名* 这里面还需要一个强转* c.getName()是一个全的* 包括包名和类名* 然后获取他的一个对象* 把它强转成父类* 即使我们传JavaVideo或者PathonVideo* 都可以强转成父类的* 所以这里面Video也就赋值成功了* * 然后调用newInstance方法* 来获取这个对象* 然后强转赋值给Video* * */video = (Video) Class.forName(c.getName()).newInstance();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}/*** 下边我们直接返回Video就可以了* */return video;}/*** 首先我们要创建一个方法* 返回值是Video* 我们还要传一个类型type* 根据type判断返回什么样的子类实现* 那这个也比较简单* 我们直接写* * 我们看一下工厂的具体实现* 现在我们要加一个算法的课程* 或者前端的课程* 我们要修改这个类的一个实现* 里面创建一个具体的* 前端课程的一个value* 也就是说随着课程的一个扩展* 我们的类要不断地修改* 而修改就会带来风险* 通过修改这个类* 来扩展具体的一个类型* 所以他并不符合开闭原则* 那我们再来看一下UML* 我们可以想象一下我们的目的是为了扩展* 那是为了对扩展开放* 和对修改关闭* 这个时候我们就可以使用工厂方法来演进一下* 我们再理会一下他们之间的差异* 之后我们再像抽象工厂演进* 然后再体会他们之间的不同* 那通过这个我们加深对工厂模式的理解* 也有把这个方法写成静态方法的* 通过静态方法来建一个简单的工厂* 这个也是比较常见的* 使用静态方法就直接调用就可以了* 不用创建VideoFactory* 因为这个方法是静态方法呢* 我们是无法改变这个行为* 如果没有被继承或者重写的* 直接使用VideoFactory是OK的* 刚刚我们对简单工厂也分析了一下* 对于简单工厂我们还可以通过反射* 来弥补简单工厂的扩展性* 利用反射来演示一下简单工厂* * * * * @param c* @return*/public Video getVideo(String type){/*** 不区分大小写* 这里使用switch也是OK的* * 这个时候判断他是一个Java视频* */if("java".equalsIgnoreCase(type)){/*** 直接返回一个Java视频* */return new JavaVideo();}else if("python".equalsIgnoreCase(type)){return new PythonVideo();}return null;}}
package com.learn.design.pattern.creational.simplefactory;/*** 对于Test这个类它是属于应用层的* 我们也可以把它理解成调用类的一个client* 所以我们接下来讲应用层代码* 无论这个类是Test还是Client* 在我们这里面都是一样的* 我们创建一个Java的视频* new一个JavaVideo* 调用它的produce方法* 如果我们需要JAVA的视频* 那现在就是一个父类的引用* 指向了子类的一个实现* 在我们这个客户端类* Test类里面* 也就是说应用层类* 它是非常依赖JavaVideo这个类的* 例如我现在想生成PythonVideo* 这个类肯定是需要改的* 那现在我们在同一个包下* 所以不需要额外的import* 所以在import这个区域* 体现不出来的* 如果我们是跨包的* 或者是需要import的时候* 就可以看到是需要依赖的类的* 那我们能不能不让我们的应用层依赖对应的类* 那我们能够把生产过程放到一个类里面* 是我们的应用层不依赖于对应的具体实现类* 这个就是一个简单工厂的一个由来* 现在我们就把创建具体的视频过程移植到简单工厂里面* 那我们现在来创建这个类* * 简单工厂有没有什么缺点* * * * @author Leon.Sun**/
public class Test {public static void main(String[] args) {/*** 现在就不直接new PathonVideo了* 我不需要直接依赖这个类* 那这里面也就不使用匿名对象了* 直接再new一个出来* * 这里面并没有具体的PathonVideo还是JavaVideo* 如果导包的时候* 不需要导具体的* JavaVideo还是PythonVideo* 我们只导入一个VideoFactory就可以了* 现在他们都是同包的* 不需要import也能够拿到它* 现在看一下最新的UML类图* * 首先new了一个VideoFactory* 这个毋庸置疑* */
// VideoFactory videoFactory = new VideoFactory();/*** 通过videoFactory的getVideo方法* 里面传一个JAVA* * 然后进入getVideo方法* * 这个时候注意Video的一个类型* 具体的指向的是JavaVideo的一个对象* 这个对象的具体类型是JavaVideo类型* 同时它也是Video类型* Video instanceof JavaVideo* 但是他不是PathonVideo类型* Video instanceof PathonVideo* 然后继续* * */
// Video video = videoFactory.getVideo("java");/*** 如果为空就直接return* */
// if(video == null){
// return;
// }/*** 然后这里直接调用JavaVideo的produce方法* 这个就是简单工厂* 非常容易理解* * */
// video.produce();VideoFactory videoFactory = new VideoFactory();/*** 这里要传对应的class* 那我们只需要传JavaVideo.class就可以了* 这样有一个扩展性* 从一定程度上满足开闭原则* 如果我们新增一个前端课程* FEVideo* 那只需要传FEVideo的类就可以了* 而这个工厂是不需要变化的* 工厂我们不需要再修改他* 我们现在来debug一下* * */Video video = videoFactory.getVideo(JavaVideo.class);if(video == null){return;}/*** 直接执行produce方法* */video.produce();}}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!