重学设计模式-工厂模式(简单工厂模式,工厂方法模式,抽象工厂模式)
在平常的学习和工作中,我们创建对象一般会直接用new,但是很多时候直接new会存在一些问题,而且直接new会让我们的代码变得非常繁杂,这时候就会巧妙的用到设计模式,平常我们通过力扣学习的算法可能并不会在我们工作中用到,但设计模式基本上我们所参加的每一个项目都会有。
今天来学习讲解一下工厂模式,这个也是我认为最常见的设计模式之一
1.什么是工厂模式
工厂模式将目的将创建对象的具体过程屏蔽隔离起来,从而达到更高的灵活性,工厂模式可以分为三类:
简单工厂模式(Simple Factory)
工厂方法模式(Factory Method)
抽象工厂模式(Abstract Factory)
这三种模式从上到下逐步抽象,并且更具一般性。《设计模式》一书中将工厂模式分为两类:工厂方法模式与抽象工厂模式。将简单工厂模式看为工厂方法模式的一种特例,两者归为一类。 我们先从学校食堂窗口案例对工厂模式做个初步的了解:
- 没有工厂模式:在没有工厂模式的情况下,我们食堂窗口就类似于米饭,馒头,面条这些都需要我们自己创建,我们需要告诉窗口具体需要什么产品,然后自己创建
- 简单工厂模式:在简单工厂模式下,我们就不需要自己创建了,而是让食堂阿姨创建,但是简单工厂模式下只有一个工厂,也就是只有一个窗口,我们需要在这一个窗口选取我们所需要的食物
- 工厂方法模式:在工厂方法模式下,每一个食物就对应一个窗口,比如说分为米饭窗口,馒头窗口,面条窗口,我们需要什么仅需要去对应窗口买就可以了
- 抽象工厂模式:在抽象工厂模式下,每一个事物可能有多种组成成分,每一个窗口,可以生成多个食品以及食品组成成分,比如说有一个清真窗口,我们需要刀削面加牛肉,或者刀削面加羊肉,就仅需在这一个清真窗口把我们所需的参数传进去,就会我们生成对应的对象。
2.简单工厂模式
简单工厂模式的逻辑就是将定义一个创建对象的接口,将接口的创建和业务逻辑分开,我们需要修改逻辑仅需要去修改工厂里面的内容即可,降低耦合性。
上面就是简单工厂的uml图,简单工厂由于比较好理解一般来说仅有一个角色就是产品工厂,我们将需要的参数提交给简单工厂,简单工厂就会将产品生产出来。
代码实现:
产品类
abstract class food {
public food(){}
}
public class noodles extends food {
public noodles () {
System.out.println("制造-->noodles ");
}
}
public class rice extends BMW{
public rice (){
System.out.println("制造-->rice ");
}
}
工厂类:
public class Factory {
public food createfood(int type) {
switch (type) {
case 1:
return new rice();
case 2:
return new noodles();
default:
break;
}
return null;
}
}
用户类:
public class Users{
Factory factory = new Factory();
food rice = factory.createfood(1);
food noodles = factory.createfood(2);
}
上述之所以用1,2仅仅是为了方便写代码。
简单工厂模式的优缺点都很明显,有点就是解耦,缺点就是我们每次增加或者修改产品都需要去修改工厂类,如果项目规模特别大的话,这显然是无法接受的。
3 工厂方法模式
工厂方法模式将工厂抽象化,并定义一个创建对象的接口。每增加新产品,只需增加该产品以及对应的具体实现工厂类,由具体工厂类决定要实例化的产品是哪个,将对象的创建与实例化延迟到子类,这样工厂的设计就符合“开闭原则”了,扩展时不必去修改原来的代码。在使用时,用于只需知道产品对应的具体工厂,关注具体的创建过程,甚至不需要知道具体产品类的类名,当我们选择哪个具体工厂时,就已经决定了实际创建的产品是哪个了。
工厂方法一半分为四个角色
抽象工厂:每个具体工厂需要继承抽象工厂,一般来说用抽象类来实现
具体工厂:需要继承抽象工厂,生产具体产品,一般是具体生产逻辑
抽象产品:具体产品需要继承,有时候也可以没有
具体产品:我们所具体需要的对象
代码示例
产品类:
abstract class food{
public food(){}
}
public class noodles extends food{
public noodles () {
System.out.println("制造-->noodles ");
}
}
public class rice extends food{
public rice (){
System.out.println("制造-->rice ");
}
}
工厂类:
interface Factoryfood {
BMW createfood();
}
public class Factorynoodles implements Factoryfood{
@Override
public noodles createfood() {
return new BMWnoodles();
}
}
public class Factoryrice implements Factoryfood {
@Override
public rice createfood() {
return new rice();
}
}
用户类:
public class Customer {
public static void main(String[] args) {
Factoryrice factoryrice = new Factoryrice();
rice = factoryrice.createrice();
Factorynoodles factorynoodles = new Factorynoodles();
noodles noodles = factorynoodles.createnoodles();
}
}
4.抽象工厂模式
工厂方法模式中,一个工厂生成具体产品,但是正如我文章开头所说,我们所需要的可能不仅仅是一个产品,而是一个产品加某些组件,或者说有几个产品我们需要在一个工厂内生产。此时工厂方法模式就不再适用。
抽象工厂模式提供一个工厂生产多个组件+产品的功能,简单的说一个工厂生产的是一个产品族
抽象工厂 AbstractFactory:定义了一个接口,这个接口包含了一组方法用来生产产品,所有的具体工厂都必须实现此接口。
具体工厂 ConcreteFactory:用于生产不同产品族,要创建一个产品,用户只需使用其中一个工厂进行获取,完全不需要实例化任何产品对象。
抽象产品 AbstractProduct:这是一个产品家族,每一个具体工厂都能够生产一整组产品。
具体产品 Product
抽象工厂相对来说没那么好理解,建议大家阅读一下下面的代码
代码示例:
产品类:
public interface Engine {}
public class EngineA implements Engine{
public EngineA(){
System.out.println("制造-->EngineA");
}
}
public class EngineB implements Engine{
public EngineB(){
System.out.println("制造-->EngineB");
}
}
public interface Aircondition {}
public class AirconditionA implements Aircondition{
public AirconditionA(){
System.out.println("制造-->AirconditionA");
}
}
public class AirconditionB implements Aircondition{
public AirconditionB(){
System.out.println("制造-->AirconditionB");
}
}
工厂类
//创建工厂的接口
public interface AbstractFactory {
public Engine createEngine();
public Aircondition createAircondition();
}
public class Factoryrice implements AbstractFactory{
@Override
public Engine createEngine() {
return new EngineA();
}
@Override
public Aircondition createAircondition() {
return new AirconditionA();
}
}
//宝马523系列
public class Factorynoodles implements AbstractFactory {
@Override
public Engine createEngine() {
return new EngineB();
}
@Override
public Aircondition createAircondition() {
return new AirconditionB();
}
}
用户类:
public class Customer {
public static void main(String[] args){
FactoryBMW320 factoryrice = new Factoryrice();
factoryBMW320.createEngine();
factoryBMW320.createAircondition();
FactoryBMW523 factorynoodles = new Factorynoodles();
factoryBMW523.createEngine();
factoryBMW523.createAircondition();
}
}
5.工厂模式小结
工厂模式主要是通过工厂这个对象来解耦,面对不同需求采用不同的工厂模式,切忌硬套代码模板
工厂模式应该是我们平常用到的最多的设计模式之一,但大家不要盲目去用,有很多用ifelse能够很简单解决的业务也可以不用工厂模式,不然到时候反而增加了我们的代码复杂度。
后面还会持续更新各种设计模式