首页 > 轻松理解工厂模式!就等面试官问了!
头像
猿兄
编辑于 2021-04-15 10:33
+ 关注

轻松理解工厂模式!就等面试官问了!

之前分享:
高频Java基础面试题
高频Java集合面试题

单列模式的6种实现方式

今天分享一些面试高频的单列模式的6种实现方式。

整理分享不易,先点赞评论收藏支持一波再看鸭~

文章目录:

1. 工厂模式介绍

工厂模式(Factory Pattern) 是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

简单来说就是: 我们创建一个工厂类,然后当调用者想要创建一个对象时,只需要告诉工厂类即可,由工厂类去创建对象,调用者无需知道是如何创建的,也不用自己去创建。

再形象点说就是: 比如我们需要购买一批电脑,我们只要把我们的需求告诉电脑工厂,电脑工厂就会帮我们把这批电脑做好,而我们是不用自己去做这个电脑的,也不用我们自己去知道这个电脑是怎么做出来的,这就是工厂模式。

工厂模式分为简单工厂模式工厂方法模式抽象工厂模式,它们都属于设计模式中的创建型模式。其主要功能都是帮助我们把对象的实例化部分抽取了出来,目的是降低系统中代码耦合度,并且增强了系统的扩展性。

下面就分别来看一下3种工厂模式。

2. 工厂模式——简单工厂模式

2.1 简单工厂模式介绍

简单工厂,简单工厂,自然是实现很简单。简单工厂模式只是将不同对象的创建操作进行了一层简单的封装,其实也就是把不同对象的创建操作全都单独放到一个类中,这个类就成为了简单工厂类;当我们需要某个对象时,只需把我们的需求告诉这个简单工厂类,然后由这个简单工厂类根据我们的需求去创建对应的对象即可。

2.2 简单工厂模式实现

  • 我们以电脑为例子,实现一个电脑工厂,由电脑工厂根据需求生成不同品牌的电脑。

1. 创建一个电脑抽象类

public abstract class Computer {
    public abstract void use();
}

2. 创建继承了电脑抽象类的,具体的不同品牌的电脑的实体类

public class HaseeComputer extends Computer {
    public HaseeComputer() {
        System.out.println("生产了神舟电脑");
    }

    @Override
    public void use() {
        System.out.println("使用了神舟电脑");
    }
}
public class LenovoComputer extends Computer {
    public LenovoComputer() {
        System.out.println("生产了联想电脑");
    }
    @Override
    public void use() {
        System.out.println("使用了联想电脑");
    }
}

3. 创建一个电脑工厂

public class ComputerFactory {
    public static Computer produceComputer(String computerBrand) {
        if (computerBrand == null) {
            return null;
        }
        if (computerBrand.equalsIgnoreCase("Hasee")) {
            return new HaseeComputer();
        }else if (computerBrand.equalsIgnoreCase("Lenovo")) {
            return new LenovoComputer();
        }
        return null;
    }
}

4. 测试:使用工厂生产不同品牌电脑并使用

public class FactoryTest {
    public static void main(String[] args) {
        ComputerFactory computerFactory = new ComputerFactory();
        Computer haseeComputer = computerFactory.produceComputer("Hasee");
        haseeComputer.use();
        Computer  lenovoComputer = computerFactory.produceComputer("Lenovo");
        lenovoComputer.use();
    }
}

2.3 简单工厂模式的优缺点

优点: 简单工厂模式可以根据需求,动态生成使用者所需类的对象,而使用者不用去知道怎么创建对象,使得各个模块各司其职,降低了系统的耦合性。

缺点: 扩展性差,违背了开闭原则(开闭原则指的是:软件实现应该对扩展开放,对修改关闭)。新增产品时,需要修改工厂类。

比如上面的实现样例中,如果我们需要一个苹果电脑时,原有的工厂类就无法生产这个苹果电脑了,这个时候就需要去修改工厂类了。

3. 工厂模式——工厂方法模式

3.1 工厂方法模式的介绍

在简单方法中,我们是只有一个工厂类,由这个工厂类负责动态的创建我们所需要的对象;而在工厂方法模式中,我们的工厂类下面还有很多子工厂类,我们需要的对象是由这些子工厂类来创建的。其实就是改进了简单工厂模式,因为当我们需要一个新产品时,只需要扩展一个新的子工厂类即可,而不用去修改原有的代码,这样就符合了开闭原则。

3.2 工厂方法模式的实现

  • 我们还说以电脑为例子,实现一个电脑工厂,再根据不同品牌实现电脑工厂子类,由电脑工厂子类根据需求生成不同品牌的电脑。

1.创建一个电脑抽象类

public abstract class Computer {
    public abstract void use();
}

2.创建继承了电脑抽象类的,具体的不同品牌的电脑的实体类

public class LenovoComputer extends Computer {
    public LenovoComputer() {
        System.out.println("生产了联想电脑");
    }
    @Override
    public void use() {
        System.out.println("生产了联想电脑");
    }
}
public class HaseeComputer extends Computer {
    public HaseeComputer() {
        System.out.println("生产了神舟电脑");
    }
    @Override
    public void use() {
        System.out.println("使用了神舟电脑");
    }
}

3.创建一个电脑抽象工厂类

public abstract class ComputerFactory {
    public abstract Computer produce();
}

4.创建电脑抽象工厂类的子类(根据不同的电脑品牌)

public class LenovoFactory extends ComputerFactory {
    @Override
    public Computer produce() {
        return new LenovoComputer();
    }
}
public class HaseeFactory extends ComputerFactory {
    @Override
    public Computer produce() {
        return new HaseeComputer();
    }
}

5. 测试:使用不同子工厂生产不同品牌电脑并使用

public class FactoryTest {
    public static void main(String[] args) {
        ComputerFactory haseeFactory = new HaseeFactory();
        Computer haseeComputer = haseeFactory.produce();
        haseeComputer.use();

        ComputerFactory lenovoFactory = new LenovoFactory();
        Computer lenovoComputer = lenovoFactory.produce();
        lenovoComputer.use();
    }
}

3.3 工厂方法模式的优缺点

优点: 扩展性好,符合了开闭原则,新增一种产品时,只需增加改对应的产品类和对应的工厂子类即可。比如样例实现中,当我们需要一个苹果电脑时,只需要去新增一个苹果电脑类和一个苹果工厂类即可,而无需去修改原有的代码。符合单一职责原则,每个工厂只负责一种产品,而不是由一个工厂去生成所有商品。

缺点: 当我们新增产品时,还需要提供对应的工厂类,系统中类的个数将会成倍增加,相当于增加了系统的复杂性。

4. 工厂模式——抽象工厂模式

4.1 抽象工厂模式的介绍

抽象工厂模式有点像是工厂方法模式的升级版。

工厂方法模式针对的某一种产品,而抽象工厂模式可以针对多种产品。

意思就是:工厂方法模式解决的是生产不同品牌的同一类型的电脑。而抽象工厂模式解决的是生产不同品牌的多种类型的电脑。

再白话些就是:工厂方法模式中的 联想电脑工厂 只能生产老式的台式电脑,而如果现在需要生产 台式电脑,笔记本电脑,平板电脑 等多个种类的电脑的话,那么工厂方法模式就不太方便了。而抽象工厂模式可以解决 联想电脑工厂 生产多个种类电脑的问题,也就是解决一个工厂生产多种类型的产品的问题。

4.2 抽象工厂模式的实现

  • 我们依旧用电脑为列子,实现一个电脑工厂,再根据不同品牌实现电脑工厂子类,由电脑工厂子类根据需求生成不同品牌的不同种类的电脑。

1. 创建各种类型的电脑抽象类

public abstract class DesktopComputer {
    public abstract void use();
}
public abstract class NotebookComputer {
    public abstract void use();
}

2. 创建具体的不同品牌的各种类型的电脑实体类

public class HaseeDesktopComputer extends DesktopComputer {
    public HaseeDesktopComputer() {
        System.out.println("生产了神舟台式电脑");
    }
    @Override
    public void use() {
        System.out.println("使用了神舟台式电脑");
    }
}
public class HaseeNotebookComputer extends NotebookComputer {
    public HaseeNotebookComputer() {
        System.out.println("生产了神舟笔记本电脑");
    }
    @Override
    public void use() {
        System.out.println("生产了神舟笔记本电脑");
    }
}
public class LenovoDesktopComputer extends DesktopComputer {
    public LenovoDesktopComputer() {
        System.out.println("生产力联想台式电脑");
    }
    @Override
    public void use() {
        System.out.println("使用了联想台式电脑");
    }
}
public class LenovoNotebookComputer extends NotebookComputer {
    public LenovoNotebookComputer() {
        System.out.println("生产了联想笔记本电脑");
    }
    @Override
    public void use() {
        System.out.println("使用了联想笔记本电脑");
    }
}

3. 创建一个电脑的抽象工厂类

public abstract class ComputerFactory {
    public abstract DesktopComputer produceDesktopComputer();
    public abstract NotebookComputer produceNotebookComputer();
}

4. 创建电脑抽象工厂类的子类(根据不同的电脑品牌)

public class HaseeFactory extends ComputerFactory {
    @Override
    public DesktopComputer produceDesktopComputer() {
        return new HaseeDesktopComputer();
    }

    @Override
    public NotebookComputer produceNotebookComputer() {
        return new HaseeNotebookComputer();
    }
}
public class LenovoFactory extends ComputerFactory {
    @Override
    public DesktopComputer produceDesktopComputer() {
        return new LenovoDesktopComputer();
    }

    @Override
    public NotebookComputer produceNotebookComputer() {
        return new LenovoNotebookComputer();
    }
}

5. 测试:使用不同子工厂创建不同品牌的不同种类的电脑

public class TestFactory {
    public static void main(String[] args) {
        ComputerFactory haseeFactory = new HaseeFactory();
        DesktopComputer haseeDesktopComputer = haseeFactory.produceDesktopComputer();
        haseeDesktopComputer.use();
        NotebookComputer haseeNotebookComputer = haseeFactory.produceNotebookComputer();
        haseeNotebookComputer.use();

        ComputerFactory lenovoFactory = new LenovoFactory();
        DesktopComputer lenovoDesktopComputer = lenovoFactory.produceDesktopComputer();
        lenovoDesktopComputer.use();
        NotebookComputer lenocoFactory  = lenovoFactory.produceNotebookComputer();
        lenocoFactory.use();

    }
}

4.3 抽象方法模式的优缺点

优点: 工厂抽象类创建了多个类型的产品,当有需求时,可以创建相关产品子类和子工厂类来获取。也就是可以满足生产不同品牌的不同类型的电脑。

简单来说就是: 开始我们的工厂方法模式,如果我们需要台式电脑,又需要笔记本电脑,要多种产品时,工厂方法模式无法满足我们的需求;而抽象方法模式,提前在抽象工厂中,定义好了可能需要的多种产品,比如 台式电脑,笔记本电脑,平板电脑等,当有需求的时候,我们只需要创建相关子类和相关子工厂类即可。

缺点: 扩展新种类产品时困难。抽象工厂模式需要我们在工厂抽象类中提前确定了可能需要的产品种类,以满足不同品牌的多种产品的需求。但是如果我们需要的产品种类并没有在工厂抽象类中提前确定,那我们就需要去修改工厂抽象类了,而一旦修改了工厂抽象类,那么所有的工厂子类也需要修改,这样显然扩展不方便。

碎碎念:

大家可能一开始对于这3种工厂模式的理解有些混淆,没有关系,我刚看的时候也没太理解三者的区别,但是我去把3种工厂模式都实现了一遍,然后再将代码和思想结合来琢磨和理解,就明白了三种的区别和思想了。所以建议大家一定要 多去动手实现,多去操作,再结合思想来琢磨,才能更好的理解一个知识。

以上就是猿兄给大家带来的关于 工厂模式 的内容了。Spring 中的 BeanFactory 就是工厂模式中的简单工厂模式的体现 ,大家可以去看看相关内容。然后我们平时设计程序时,也可以考虑使用工厂模式的思想,对于优秀的程序设计是有很大的帮助的。

注:如果这篇分享有任何错误和建议,欢迎大家留言,不胜感激!

如果这篇分享对你有帮助的话,点个赞鸭!

全部评论

(5) 回帖
加载中...
话题 回帖

推荐话题

相关热帖

热门推荐