设计模式-简单工厂
简单工厂(factory)模式:是个人都会的设计模式
相关面试说明:
平时面试的一个段子:一般面试时,设计模式是必问的,因为这个东西很重要,设计模式掌握的好不好,决定了会不会写出屎一样的代码。最讨厌的其实就是,在自己的team里面,有同学在这个复杂的系统里面,去制造出来屎一样的代码,然后就导致,这个同学如果一旦离职了以后,后面整个系统很难 维护、扩展、升级,修复bug。
但是从大量的面试中,可以分享一个结论,就是基本上 你面100个人,90个人,差不多就是90%这个比例,然后会告诉你,他说,我就会这个 工厂模式 和 单例模式,呵,真实一个笑话啊,身为一个工作几年的程序员来说,就会 工厂模式 和 单例模式,但是这个东西,基本上也验证了说,为什么 简单工厂模式是 是个人都会的设计模式,因为基本上 我就从来没有遇到过一个人说,连工厂模式都不会用的啊。
那这个模式因为它太简单了,所以就快速的来说一下。
不用简单工厂模式的代码实现:
假设说,我们现在需要,生产出来了一个对象Product,然后我们如果不用模式的话,是怎么来做。。。
首先,创建一个类,叫WithoutFactoryPatternDemo,其中,
比如说,我们这边来定义一个静态类Product,我们要创建出来这么一个产品Product;
然后 private String name;,其中有一个属性name;
然后 添加构造函数,get/set/toString方法,再写一个main方法;
现在假设说,我们就要创建Product这样一个对象,要怎么来做;
main方法中 Product product = new Product("测试产品");,然后 执行输出一下 System.out.println("product");,输出结果为 Product [name=测试产品]。
代码如下:
public class WithoutFactoryPatternDemo { public static void main(String[] args) { Product product = new Product("测试产品"); System.out.println(product); } public static class Product { private String name; public Product(String name) { super(); this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Product{" + "name='" + name + '\'' + '}'; } } }
不用简单工厂模式的问题所在:
那这段代码有什么问题,ok,很简单。如果你直接面向一个类来编程,直接通过new来创建类的实例的话,你基本上就是,后面会死的很惨啊。
假设,我们如果对这个Product,要更换一个类,就是换一个类的实现,此时就必须在,创建这个实例 和 所有调用这个类实例 的地方,都要修改一下这个代码,什么意思。
我现在把这个Product,给它改成,叫做Product2,然后构造方法也要随着改成Product2。
public class WithoutFactoryPatternDemo { public static void main(String[] args) { Product2 product = new Product2("测试产品"); System.out.println(product); } public static class Product2 { private String name; public Product2(String name) { super(); this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Product{" + "name='" + name + '\'' + '}'; } } }
然后你看,你一改这个类名Product为Product2,main方法中调用Product的逻辑就报错了,就要改成Product2 product = new Product2("测试产品");,
那这样好么,如果你有100个地方都,创建了Product这个类的实例,你需要在100个地方啊,都去修改这个new Product()的这段代码,这个代码可维护性,和可扩展性之差,惨目忍睹,垃圾代码,这就是垃圾代码。
应用简单工厂模式的代码实现:
那么,为了去避免这个问题,最简单的方式,应该怎么去做,就是用这个FactoryPatternDemo,简单工厂模式。
首先,我们先来定义一个接口,Product,接口中定义一个方法void execute();。
然后的话呢,这边的话是,然后我们是定义一个静态的Product接口的实现类,public static class ProductImpl1 implement Product{... },
在execute方法实现中输出一句话,产品1的功能实现。System.out.println("产品1的功能实现");,
然后我们再定义一个工厂ProductFactory,public static class ProductFactory{...},
里面有一个静态方法create(),public static Product create(){ return new ProductImpl1();},方法里面返回ProductImpl1的实现。
然后这个main方法里面,这时 如果再要创建Product这个对象怎么创建,Product product = ProductFactory.create();,然后product.execute();,
我们输出来看一下,ok,产品1的功能实现。
public class FactoryPatternDemo { public static void main(String[] args) { Product product = ProductFactory.create(); product.execute(); } public interface Product{ void execute(); } public static class ProductImpl1 implements Product { @Override public void execute() { System.out.println("产品1的功能实现"); } } public static class ProductFactory { public static Product create(){ return new ProductImpl1(); } } }
使用工厂模式的好处:
好,我们这个,它的整个核心思路是什么,就是绝对不在任何一个,就是要使用Product这个类的地方,然后手动去new一个类出来,而是把new这个类的这个操作,转移到一个工厂里面去,然后你找这个工厂的一个静态方法,这个工厂的静态方法里面就给你创建一个对象,给你返回回来,也就是说,选择说创建哪个类的实例的这个过程(比如ProductImpl1),放在这个工厂里面了,然后我们面向这个,要使用这个对象的接口Product,面向接口去编程。这个Product是个接口对吧.
好,这个时候假设说,我把这个ProductImpl1,给它改成ProductImpl2,那么只要在这(ProductFactory)工厂的静态方法中改一下,把返回new的ProductImpl1的实例,改为返回new的ProductImpl2的实例,就可以。然后main方法中调用Product的代码,变都不用变,连动都不用动,这就是面向接口编程,然后从工厂里面拿对象实例的这个好处,这就是所谓的工厂模式啊。那么,如果此时有100个地方啊,都需要获取这个,Product这个实例,对吧,但是此时这个Product的实现类 改了,我们只要修改一个地方即可。就是那个ProductFactory中,ok,这个就是它的一个好处。
工厂模式最常见的实际应用场景:
工厂模式,这个实在是太简单了,所以说,在真正企业的这个实际运用中,其实工厂模式,真正真正,就是最最常见的实践就是Spring啊。因为Spring容器就是一个大工厂,一个概念,就是Spring会基于这个xml,或者是这个注解,就是根据一些配置,然后去创建出来所有我们需要的类的实例,就比如说,我们现在搞了一个
@Service
public class UserServiceImpl implement UserService{}
这个东西,那么这个时候,其实Spring看到这个@Service注解,它就会去创建 一个UserServiceImpl它的这个实例出来,然后把它放到,Spring自己内部的这个容器里面,这个,此时Spring就相当于是个工厂,它里面什么实例都有,然后,我们如果要使用UserService的地方,比如说咱们写了一个
public class UserController{
@Autowired
private UserService userService;
}
这个里面怎么去使用,直接,就是可能@Autowired,然后private UserService userService,面向接口,面向UserService这个接口编程,然后Spring这个工厂会扫描到这个注解@Autowired,会自动把UserServiceImpl这个类的实例给注入进来,把这个实例注入给这个UserService接口在UserController这里用。
ok,那么通过这样的方式,UserController这块,是不care说,它这个UserService的接口实现类是谁的,一旦说我们要把这个UserServiceImpl给它改了UserServiceImpl2,ok,没问题啊,这个UserController这个类,完全不用做任何的这个修改,那么Spring会找到UserServiceImpl2这个类,去初始化UserServiceImpl2的这个类的实例,然后,把这个类的实例,给注入到UserController调用者这里来。
所以说,Spring本身就是一个工厂模式,最好最好的一个体现啊。也就是说我们那个,在项目中大量的用SpringIOC这块功能,其实本身就是在实践工厂模式,但是,如果我们自己要实现,我们自己如果要去这个工厂的话,其实也是有这种场景的。在后续的电商项目里面,我们会把工厂模式,跟构造器模式结合起来,还有一些别的模式,会结合具体的业务去演示,怎么自己去做工厂模式实现,怎么去做。
ok,也就是说这个模式,首先,你用Spring就是在实践,另外,我们为了自己手动实现去体验,我们会结合电商的业务演示怎么去用。