设计模式-简单工厂

简单工厂(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就是在实践,另外,我们为了自己手动实现去体验,我们会结合电商的业务演示怎么去用。

 

end

posted @ 2022-06-29 12:00  HarryVan  阅读(24)  评论(0编辑  收藏  举报