工厂模式(又名静态工厂)


工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
其实我们平时经常遇到这种模式:
比如:factory. creatConnection()
factory.getBean()等等这种写法我们是不是非常熟悉,只是很少去追踪这个地方底层到底怎么实现的

举例: 我们吃面包会想这个面包如何 制作的吗? 我们买牛奶会关系如何制作的吗?我们买汽车我们关系如何组装生产的吗? 按道理说是不会关心的,为啥? 这些专业的有专业的人去关心,我们作为消费者没有精力关注,也没有能力关注,这样就简化了我们的使用端的压力

简单工厂模式

在这里插入图片描述
代码:

public interface Car {
    String color = "red";
    int wheelnum = 4;
    public void getBrand();
}
public class AoDiCar  implements Car {


    public void getBrand() {
        System.out.println("我的品牌是: "+this.getClass().getSimpleName());
    }
}
public class BenChiCar  implements Car {
    public void getBrand() {
        System.out.println("我的品牌是: "+this.getClass().getSimpleName());
    }
}
public class BMWCar implements Car {
    public void getBrand() {
        System.out.println("我的品牌是: "+this.getClass().getSimpleName());
    }
}
public class CarFactory {

    public static Car creatCar(String carType){

        //创建过程以及创建逻辑
        if("aodi".equals(carType)){
            return new AoDiCar();
        }
        if("bmw".equals(carType)){
            return new BMWCar();
        }
        if("aodi".equals(carType)){
            return new BenChiCar();
        }
        return null;
    }
}
public class Client {

    public static void main(String[] args) {
        Car bmw = CarFactory.creatCar("bmw");
        bmw.getBrand();

        Car aodi = CarFactory.creatCar("aodi");
        aodi.getBrand();
    }
}

简单工厂就犹如他的名字一样简单,我们可以从中看到优点和确定
优点: 1、一个调用者想创建一个对象,只要知道其名称就可以了。
2、扩展性高,如果想增加一个品牌汽车,只要扩展一个工厂类就可以。
3、屏蔽汽车的具体实现,调用者只关心汽车的接口。

缺点:每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。

这种模式在我们内部使用的类非常简单,这种模式不符合开闭原则,无法提供扩展对第三方

工厂方法

在这里插入图片描述
代码:

public interface Factory {
    Car creatCar();
}

public class AudiFactory implements Factory {
    @Override
    public Car creatCar() {
        return new AoDiCar();
    }
}
public class BMWFactory implements Factory {
    @Override
    public Car creatCar() {
        return new BMWCar();
    }
}
public class Client {


    public static void main(String[] args) {
        Factory factory = new AudiFactory();
        Car car = factory.creatCar();
        car.getBrand();
    }
}

这个方法已经很把我们上面说的不能让第三方扩展的问题解决了,但是同样我们也发现了另外的问题,就是客户端调用复杂了,我们还得知道工厂创建,有没有办法解决这个问题?

JDK中的使用

Integer n = Integer.valueOf(100);
Integer既是产品又是静态工厂。它提供了静态方法valueOf()来创建Integer。那么这种方式和直接写new Integer(100)有何区别呢?我们观察valueOf()方法

public final class Integer {
    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
    ...
}

它的好处在于,valueOf()内部可能会使用new创建一个新的Integer实例,但也可能直接返回一个缓存的Integer实例。对于调用方来说,没必要知道Integer创建的细节。

工厂方法可以隐藏创建产品的细节,且不一定每次都会真正创建产品,完全可以返回缓存的产品,从而提升速度并减少内存消耗。

如果调用方直接使用Integer n = new Integer(100),那么就失去了使用缓存优化的可能性。

我们经常使用的另一个静态工厂方法是List.of():

List<String> list = List.of("A", "B", "C");

这个静态工厂方法接收可变参数,然后返回List接口。需要注意的是,调用方获取的产品总是List接口,而且并不关心它的实际类型。即使调用方知道List产品的实际类型是java.util.ImmutableCollections$ListN,也不要去强制转型为子类,因为静态工厂方法List.of()保证返回List,但也完全可以修改为返回java.util.ArrayList。这就是里氏替换原则:返回实现接口的任意子类都可以满足该方法的要求,且不影响调用方。

总是引用接口而非实现类,能允许变换子类而不影响调用方,即尽可能面向抽象编程。
和List.of()类似,我们使用MessageDigest时,为了创建某个摘要算法,总是使用静态工厂方法getInstance(String):

MessageDigest md5 = MessageDigest.getInstance("MD5");
MessageDigest sha1 = MessageDigest.getInstance("SHA-1");

调用方通过产品名称获得产品实例,不但调用简单,而且获得的引用仍然是MessageDigest这个抽象类。

简单了解下spring中如何使用

算了今天太晚了,已经凌晨一点多了,明天还上班,到时候在spring源码专题里面再写吧。。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值