工厂模式

2019-06-26 17:07:30 浏览数 (1)

前言

在23中设计模式中,工厂方法属于创建型的设计模式,只有工厂方法和抽象工厂两种,但是实际我们常与简单工厂混淆,因为简单工厂模式违背了开闭原则。

什么是开闭原则:开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类,后面的具体设计中我们会提到这点。

所以简单工厂不属于设计模式内的,但是并不是说简单工厂是错误的,只是根据具体情况使用而已。

下面我就针对简单工厂、工厂方法、抽象工厂结合Demo演示给大家。

正文

如图,就是工厂模式的划分。

简单工厂

概念:一个工厂类根据传入的参量决定创建出那一种产品类的实例。

想象一下汽车生产厂生产汽车,有两个工厂,分别是宝马和奔驰,客户想要买这两种车,就要分别去这两个工厂去买,结合在代码里就是客户分别传递不同的参数才可以得到不同的对象。

首先我们需要一个接口,用来返回不同的品牌的汽车。

代码语言:javascript复制
public interface Car {
    void produce();
}

然后我们需要两个汽车

代码语言:javascript复制
public class Benz implements Car {
    public void produce() {
        System.out.println("生产一辆奔驰");
    }
}
代码语言:javascript复制
public class BMW implements Car {
    public void produce() {
        System.out.println("生产一辆宝马");
    }
}

接下来就是工厂,这个工厂就是根据客户传过来的不同参数返回不同的汽车。

代码语言:javascript复制
public class CarFactory {
    public Car produce(String type) {
        if ("bmw".equals(type)) {
            return new BMW();
        } else if ("benz".equals(type)) {
            return new Benz();
        } else {
            System.out.println("类型错误");
        }
        return null;
    }
}

最后来了一个顾客说是要买宝马,让我们来测试一下吧

代码语言:javascript复制
public class SimpleFactoryTest {
    public static void main(String[] args) {
        CarFactory factory = new CarFactory();
        Car car = factory.produce("bmw");
        car.produce();
    }
}

大家看代码可以得知,现在是两个车,就要写两个if去判断,如果以后出现很多个产品那么就就要在工厂方法里写多个if ,这样就会造成拓展业务需要修改原有代码来实现,这样的写法可以实现,但是很low,建议同学们尝试以下两种。

工厂方法模式

概念:定义一个创建对象的接口,让子类决定实例化那个类。

工厂模式细分的话有两种,我在代码里会讲解一种,另一种在示例代码中体现,被我注释掉的就是普通工厂方法,大家一看便知。

与简单工厂重复的代码我就贴在一个代码块中了。

代码语言:javascript复制
public interface Car {
    void produce();
}

public class Benz implements Car {
    public void produce() {
        System.out.println("生产一辆奔驰");
    }
}

public class BMW implements Car {
    public void produce() {
        System.out.println("生产一辆宝马");
    }
}

不同的地方就是工厂的写法,我们一个汽车品牌就新建一个工厂方法。

代码语言:javascript复制
public class BenzCarFactory {
    /**
     * 工厂方法
     * @return
     */
//    public Car produceBenz() {
//        return new Benz();
//    }

    /**
     * 静态工厂方法
     *
     * @return
     */

    public static Car produceBenz() {
        return new Benz();
    }
}
代码语言:javascript复制
public class BMWCarFactory {
    /**
     * 工厂方法
     * @return
     */
//    public Car produceBMW() {
//        return new BMW();
//    }
    
    /**
     * 静态工厂方法
     *
     * @return
     */
    public static Car produceBMW() {
        return new BMW();
    }
}

因为只静态的方法,那么在jvm加载时就已经创建了,所以我们在引用的时候就不用new工厂对象了,这也是普通工厂方法与静态工厂方法的区别所在。

让我们看一下客户是怎么购买汽车的。

代码语言:javascript复制
public class FactoryMethodTest {
    //psvm
    public static void main(String[] args) {
        /**
         * 工厂方法
         */
//        BenzCarFactory factory = new BenzCarFactory();
//        Car car = factory.produceBenz();
//        car.produce();

        /**
         * 静态工厂方法
         */
        Car car = BenzCarFactory.produceBenz();
        car.produce();
    }
}

可以看出,每个工厂只生产一种产品,客户端通过不同的工厂去生产不同的产品。这样做的好处就是我们对业务进行拓展时不用更改代码,只需要新增一个拓展对产品或者对象就可以,这也是最简单也是我认为最常用对工厂方法了。

抽象工厂

概念:创建相关或依赖对象的家族,而无需明确指定具体类。

抽象工厂适用于复杂业务需求,复杂的产品生产场景中。怎么复杂呢?就是产品属性多了一个纬度,之前我们都是生产汽车,但是现在要区分出生产的颜色,对汽车的要求不仅仅是品牌还有颜色了。

来看看具体的代码实现:

首先定义三种颜色的接口

代码语言:javascript复制
public interface Black {
    void create();
}

public interface Red {
    void create();
}


public interface White {
    void create();
}

然后定义我们存在的产品,我们现在只有黑色奔驰,黑色宝马,白色奔驰,白色宝马,红色奥迪。分别创建这五个产品的类。

代码语言:javascript复制
public class BenzBlack implements Black {
    public void create() {
        System.out.println("黑色奔驰");
    }
}

public class BenzWhite implements White {
    public void create() {
        System.out.println("白色奔驰");
    }
}


public class BMWBlack implements Black {
    public void create() {
        System.out.println("黑色宝马");
    }
}

public class BMWWhite implements White {
    public void create() {
        System.out.println("白色宝马");
    }
}

public class RedAudi implements Red {
    public void create() {
        System.out.println("红色奥迪");
    }
}

然后我们定义工厂接口,工厂接口是把刚才颜色接口进行了统一整理在一起。说明我们现在可以生产这三种颜色任意品牌汽车。

所以说对业务拓展性非常高。

代码语言:javascript复制
public interface CarFactory {
    Black black();

    White white();

    Red red();
}

那么就让我们随意创建三种汽车的工厂。

代码语言:javascript复制
public class AudiFactory  implements CarFactory{
    public Black black() {
        return null;
    }

    public White white() {
        return null;
    }

    public Red red() {
        return new RedAudi();
    }
}

public class BenzFactory implements CarFactory {
    
    public Black black() {
        return  new BenzBlack();
    }

    public White white() {
        return new BenzWhite();
    }

    public Red red() {
        return null;
    }
}

public class BMWFactory implements CarFactory {
    public Black black() {
        return new BMWBlack();
    }

    public White white() {
        return new BMWWhite();
    }

    public Red red() {
        return null;
    }
}

让我们来测试一下

代码语言:javascript复制
public class AbstractFactoryMethodTest {
    public static void main(String[] args) {
        AudiFactory audi = new AudiFactory();
        Red redAudi = audi.red();
        redAudi.create();

        BenzFactory benz = new BenzFactory();
        Black blackBenz = benz.black();
        blackBenz.create();

    }
}

输出结果如下

如果要对以上代码有疑问,或者想要代码,可以加我微信 15524579896

总结

简单工厂模式适用于工厂类需要创建的对象比较少的情况,客户只需要传入具体的参数,就可以忽略工厂的生产细节,去获取想要的对象;

工厂方法模式,主要是针对单一产品结构的情景,拓展时只需增加一个工厂类就可以;

抽象工厂模式则是针对多级产品结构(系列产品)的一种工厂模式,拓展时增加多个类,改动比较大;

最后在说一下,每种模式都有自己的优点和弊端,没有最好的模式,只有最适合的模式,只要符合实际开发需求就是最好的。

0 人点赞