设计模式之工厂模式

目录

1、什么是工厂模式

2、为什么要用工厂模式

3、简单工厂模式

4、工厂方法模式

5、抽象工厂模式


前言:本文简要介绍了工厂模式,其中包含了23种设计模式中的“工厂方法模式”和“抽象工厂模式”。

1、什么是工厂模式

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

2、为什么要用工厂模式

我们先来看一个例子: 

以下是咖啡接口和它的两个实现类:

public interface Coffee { //咖啡接口

}
public class LatteCoffee implements Coffee{ //拿铁咖啡实现类

}
public class AmericaCoffee implements Coffee { //美式咖啡实现类

}

我们有一个业务如下:根据用户的需求来给用户相应的咖啡,那么关键代码如下:

        String str;//用户需求的咖啡
        if(str.equals("LatteCoffee")){
            return new LatteCoffee();
        }else if (str.equals("AmericaCoffee")){
            return new AmericaCoffee();
        }

大家乍一看是不是感觉没什么问题,但是如果我此时加一个“卡布奇诺咖啡”呢?是不是我们要去修改源代码?是不是就违反了我们软件设计原则中的“开闭原则”?而且如果我这一段代码在很多程序中都需要使用,是不是我就要修改无数个地方的代码,不仅麻烦而且可能会一不小心就修改错代码了。不仅如此,如果我们真这样写代码的话,“耦合性”可就太大了!以上就是为什么我们要用工厂设计模式的原因。

(这里有一种解耦的搭配方式:简单工厂模式+配置文件,这种搭配能达到不用修改原代码,当有类变更时,只需要修改配置文件即可,大家感兴趣可以去搜一下,本文不详细讲解)

那么,工厂设计模式有哪几种呢?可以粗略分为以下几种:①简单工厂模式 ②工厂方法模式 ③抽象工厂模式。

3、简单工厂模式

简单工厂模式不属于23大设计模式之一,因此与其说是一种设计模式,不如说是一种好的开发习惯,它主要就是利用了“封装”的思想,把我们以上创建各种“coffee”的工作交给了“工厂类”,而不是直接的在我们程序中来创建:

public class CoffeFactory  {
    public Coffee createCoffee(String type){ //创建客户需要的咖啡
        if(type.equals("LatteCoffee"))return new LatteCoffee();
        if(type.equals("AmericaCoffee"))return new AmericaCoffee();
        return null;
    }
}

可见,如果我们使用简单工厂,我们以后如果想加入某个咖啡后,并不需要去修改我们所有用到咖啡的程序中的逻辑,只需要修改CoffeeFactory类里的createCoffee()方法的逻辑即可,大大降低了我们程序的耦合度。

因此,简单工厂的优点如下:

封装了创建对象的过程,可以通过参数直接获取对象。把对象的创建和业务逻辑层分开,这样以后就避免了修改客户代码,如果要实现新产品直接修改工厂类,而不需要在原代码中修改,这样就降低了客户代码修改的可能性,更加容易扩展。

但大家可以注意到:我们上述优点中说了无需修改原代码,只需要修改工厂类,是不是还是不满足我们的“开闭原则”,那么如何解决这个问题呢?这就需要用到我们接下来说的“工厂方法模式”。

4、工厂方法模式

我们仅需将以上“CoffeeFactory”的代码变为如下:

public abstract class CoffeeFactory  { //抽象咖啡工厂
    public abstract Coffee createCoffee();//创建客户需要的咖啡
}

然后加入两个它的实现类:

public class AmericaCoffeeFactory extends CoffeeFactory {
    @Override
    public Coffee createCoffee() {
        return new AmericaCoffee();
    }
}
public class LatteCoffeeFactory extends CoffeeFactory {
    @Override
    public Coffee createCoffee() {
        return new LatteCoffee();
    }
}

此时,我们创建咖啡时,只需要将对应的工厂类赋值给对应变量即可,代码如下:

public class CoffeeStore {
    CoffeeFactory factory;
    public CoffeeStore(CoffeeFactory coffeeFactory){
        this.factory=coffeeFactory;
    }
    public Coffee createCoffee(){
        return factory.createCoffee();
    }
}

此时,我们只需要在“卖咖啡”的时候,告诉程序我们需要哪个咖啡工厂,即可得到对应的咖啡。这样屏蔽了内部创建咖啡的过程。而且最大的优点是如果此时我们想修改咖啡的种类,比如我们多加入一个“卡布奇诺”咖啡,我们只需要新创建一个卡布奇诺的咖啡类和对应的咖啡工厂即可,完美符合“开闭原则”。

因此工厂方法模式的优点如下:

不仅继承了简单工厂模式的所有优点(解耦,创建过程与使用过程分离开来,不会相互干扰),还解决了简单工厂模式不符合“开闭原则”的缺点。

但是,工厂方法模式真的“无懈可击”了吗?不!大家在仔细思考后会发现:虽然我们解决了开闭原则的问题,但是依然存在以下问题:

①如果咖啡种类很多,那我们是不是就要创建很多个“咖啡类”和很多个“咖啡工厂类”,是不是就会发生“类爆炸”。

②这种模式仅能创建一种产品,如果我们此时需要多个产品呢?

针对以上第二个问题,我们有了一个更高级的模式:“抽象工厂模式”。

5、抽象工厂模式

在说抽象工厂模式前,我们先来看一个图片:

设计模式之工厂模式_第1张图片

同一级别:同一个类型的产品,如苹果手机和华为手机就是同一级别。

同一产品族:同一个产商生产的产品,如苹果手机和苹果电脑就是同一产品族。

我们的“工厂方法模式”,仅仅能产生一个产品, 而我们的“抽象工厂模式”可以说是其的一种升级,它能产生同一产品族的多个产品,比如我们上述代码的咖啡工厂(“CoffeeFactory”)只能生产咖啡,而此时如果我们用抽象工厂模式,可以让它除了“Coffee”外还可以生产“Dessert”(甜点)之类的。代码如下:

public abstract class CoffeeFactory  { //抽象咖啡工厂
    public abstract Coffee createCoffee();//创建客户需要的咖啡
    public abstract Dessert createDessert();//创建客户需要的咖啡
}
public class LatteCoffeeFactory extends CoffeeFactory {
    @Override
    public Coffee createCoffee() {
        return new LatteCoffee();
    }

    @Override
    public Dessert createDessert() {
        return new LatteDessert();
    }
}
public class AmericaCoffeeFactory extends CoffeeFactory {
    @Override
    public Coffee createCoffee() {
        return new AmericaCoffee();
    }

    @Override
    public Dessert createDessert() {
        return new AmericaDessert();
    }
}

优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
缺点:当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。
使用场景:
当需要创建的对象是一系列相互关联或相互依赖的产品族时,如电器工厂中的电视机、洗衣机、空
调等。
系统中有多个产品族,但每次只使用其中的某一族产品。如有人只喜欢穿某一个品牌的衣服和鞋。
系统中提供了产品的类库,且所有产品的接口相同,客户端不依赖产品实例的创建细节和内部结
构。
如:输入法换皮肤,一整套一起换。生成不同操作系统的程序。

你可能感兴趣的:(设计模式,设计模式,java,开发语言)