Java设计模式1:抽象工厂模式(Abstract Factory)

意图

提供一个创建一系列相关或相互依赖对象的接口,而无需制定他们具体的类

适用性

一下情况可以使用Abstract Factory模式

一个系统要独立于它的产品的创建、组合和表示时

一个系统要由多个产品系列中的一个来配置时

当你要强调一系列相关的产品对象的设计以便进行联合使用时

当你提供一个产品类库,而指向显示他们的接口而不是实现时`
结构

这里写图片描述

AbstractProductA 和 AbstractProductB是两个抽象的产品,之所以为抽象,是因为他们都有可能有两种或多种不同的实现,ProductA1、ProductA2和ProductB1、ProductB2 就是对两个抽象产品的具体分类的实现。

AbstractFactory 则是一个抽象的工厂接口,它里面应该包含所有的产品创建的抽象方法。而ConcreteFactory 1 和 ConcreteFactory 2 就是具体的工厂了。

我们通常是在运行时再创建一个 ConcreteFactory 类的实例对象,这个具体的工厂再创建具有特定实现的产品对象,也就是说,为创建不同的产品对象,客户端应该使用不同的具体工厂。

AbstractFactory模式的优缺点

1、分离了具体的类,解耦

2、易于交换产品系列

3、有利于产品的一致性

4、难以支持新品种的产品

实现

假设你现在是客户,要买一辆车。

public class Client {

    public static void main(String[] args){
        BenzS600 benzCar = new BenzS600();
        benzCar.drive();
    }
}

问题在哪里呢,就是我们在代码里面把对象BenzS600直接new出来了,如果我们需求改变,当然这里不明显,你可以理解为,原来我们使用MySql作为数据库,但是现在我们要使用Oracle,那么我们所有的写死的代码全要改,这就是耦合度太高引起的“牵一发而动全身”,现在呢,我们可以使用抽象工厂模式,我们可以通过抽象工厂去获取对应产品的工厂(FerrariFactory),然后具体的工厂去给我们提车,而我们需求变了之后,只需要找到对应的工厂,告诉他们我们要买什么车就行了。

我们现在来设计一下

超级工厂类
package abstractFactory;

/**
 * @Author fitz.bai
 * @Date 2018/8/26 15:15
 */
public class FactoryProducer {
    public static AbstractFactory getFactory(String type) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        Class cl = Class.forName(type);
        System.out.println("创建工厂" + type);
        return (AbstractFactory) cl.newInstance();
    }
}
抽象工厂类
package abstractFactory;

/**
 * @Author fitz.bai
 * @Date 2018/8/26 15:15
 */
public abstract class AbstractFactory {
    public abstract Car getCar(String type) throws ClassNotFoundException, IllegalAccessException, InstantiationException;
}
工厂类
package abstractFactory;

/**
 * @Author fitz.bai
 * @Date 2018/8/26 15:15
 */
public class BenzFactory extends AbstractFactory {
    @Override
    public Car getCar(String type) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        Class cl = Class.forName(type);
        return (BenzCar) cl.newInstance();
    }
}
package abstractFactory;

/**
 * @Author fitz.bai
 * @Date 2018/8/26 15:15
 */
public class FerrariFactory extends AbstractFactory {

    @Override
    public Car getCar(String type) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        Class cl = Class.forName(type);
        return (FerrariCar) cl.newInstance();
    }
}
汽车类
package abstractFactory;

/**
 * @Author fitz.bai
 * @Date 2018/8/26 15:05
 * 最高级的抽象产品
 */
public interface Car {
    abstract void drive();
}
法拉利4S
package abstractFactory;

/**
 * @Author fitz.bai
 * @Date 2018/8/26 15:07
 * 抽象产品
 */
public abstract class FerrariCar implements Car {
}

package abstractFactory;

/**
 * @Author fitz.bai
 * @Date 2018/8/26 15:09
 * 具体的产品Ferrari430
 */
public class Ferrari430 extends FerrariCar {
    @Override
    public void drive() {
        System.out.println("Ferrari 430 come......");
    }
}

package abstractFactory;

/**
 * @Author fitz.bai
 * @Date 2018/8/26 15:11
 */
public class FerrariLaFerrari extends FerrariCar {
    @Override
    public void drive() {
        System.out.println("Ferrari LaFerrari come......");
    }
}
奔驰4S
package abstractFactory;

/**
 * @Author fitz.bai
 * @Date 2018/8/26 15:12
 */
public abstract class BenzCar implements Car {
}

package abstractFactory;

/**
 * @Author fitz.bai
 * @Date 2018/8/26 15:13
 */
public class BenzGLS450 extends BenzCar {
    @Override
    piublic void drive() {
        System.out.println("Benz GLS450 come......");
    }
}

package abstractFactory;

/**
 * @Author fitz.bai
 * @Date 2018/8/26 15:13
 */
public class BenzS600 extends BenzCar {
    @Override
    public void drive() {
        System.out.println("Benz S600 come......");
    }
}
买车了
package abstractFactory;

/**
 * @Author fitz.bai
 * @Date 2018/8/26 15:22
 */
public class Client {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException {

        AbstractFactory abstractFactory = FactoryProducer.getFactory("abstractFactory.FerrariFactory");

        Car ferrariCar = abstractFactory.getCar("abstractFactory.Ferrari430");
        ferrariCar.drive();

        Car ferrariLaFeCar = abstractFactory.getCar("abstractFactory.FerrariLaFerrari");
        ferrariLaFeCar.drive();

        AbstractFactory abstractFactory1 = FactoryProducer.getFactory("abstractFactory.BenzFactory");

        Car benzCar = abstractFactory1.getCar("abstractFactory.BenzS600");
        benzCar.drive();

        Car benzCar1 = abstractFactory1.getCar("abstractFactory.BenzGLS450");
        benzCar1.drive();
    }
}
/**
创建工厂abstractFactory.FerrariFactory
Ferrari 430 come......
Ferrari LaFerrari come......
创建工厂abstractFactory.BenzFactory
Benz S600 come......
Benz GLS450 come......
*/

从结果看出,我们首先提供工厂名字,抽象工厂给我们找到了具体的工厂,然后我们又告诉他我们需要什么车,他就给了我我们什么车。
还有一个问题,假如有一天我的项目想进行一个重构,重整类路径,包路径,比方说生产Ferrari430的地方有100处,getCar(type)岂不是要修改100处?当然不用,我们可以写在配置文件里面。

实际应用

JDK中的抽象工厂模式有很多应用,典型的比如线程池。我们使用线程池的时候,可以使用ThreadPoolExecutor,根据自己的喜好传入corePoolSize、maximumPoolSize、keepAliveTime、unit、workQueue、threadFactory、handler这几个参数,new出一个指定的ThreadPoolExecutor出来。

JDK给开发者提供了Executors这个类,可以让用户产生ThreadPoolExecutor和使用ThreadPoolExecutor分离开,比如可以让Executors提供一个单线程的线程池Executors.newSingleThreadExecutor()、让Executors提供一个无界线程池Executors.newCachedThreadPool()等,这样,开发者可以不用关心线程池是如何去实现的,直接使用Executors方法提供给开发者的ThreadPoolExecutor就可以了。

可以对照上面的结构图,看看线程池实现的源码,再深入了解AbstractFactory Pattern。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值