工厂模式
工厂模式结构
- 一个抽象产品 -->(理解成产品模板)
- 若干个具体产品 -->(可扩展)
- 一个抽象工厂 -->(理解成工厂模板)
- 若干个具体工厂 -->(可扩展)
工厂模式特点
- 注重用户体验的傻瓜式操作:客户(或者说调用方)的目的是获取具体产品。在这个过程中,客户无需关注具体产品的实现或者创建过程,只需要对照说明书,召唤一个工厂,然后这个工厂会为客户提供现成的产品;
- 可扩展性:现有的AB两个产品无法满足客户的要求,因此打算再提供C产品。在提供C产品的过程中,无需对抽象产品和抽象工厂做任何修改,只需提供一个具体产品和一个具体工厂。
讲个故事
场景:逆丰快递公司有一条卡车生产线,卡车业务也不错。现在老总有点飘,搞了一条飞机生产线,然后用飞机送快递。
对照工厂模式结构,先看抽象产品和具体产品:
// 抽象产品
// 不用interface,用抽象类也可以。
public interface Transport {
// 装货
void load();
// 运送
void travel();
}
// 具体产品1 :卡车
public class Truck implements Transport {
@Override
public void load() {
System.out.println("卡车带货");
}
@Override
public void travel() {
System.out.println("卡车在路上行驶");
}
}
// 具体产品2 :飞机
public class Airplane implements Transport{
@Override
public void load() {
System.out.println("飞机带货");
}
@Override
public void travel() {
System.out.println("飞机在天上行驶");
}
}
再看抽象工厂和具体工厂部分:
// 抽象工厂
public abstract class TransportFactory {
public TransportFactory(){
System.out.println("transport工厂启动...");
}
// 这里的创建对象是Transport,而不是具体的Truck或Airplane,从而保证了扩展性
public abstract Transport createTransport();
}
// 抽象工厂1:卡车工厂
public class TruckFactory extends TransportFactory {
@Override
public Transport createTransport() {
System.out.println("卡车工厂制造卡车");
return new Truck();
}
}
// 抽象工厂2:飞机工厂
public class AirplaneFactory extends TransportFactory{
@Override
public Transport createTransport() {
System.out.println("飞机工厂制造飞机");
return new Airplane();
}
}
注意抽象工厂里的抽象方法public abstract Transport createTransport(),返回类型是抽象产品Transport而不是具体产品。利用具体产品对抽象产品的继承(或者说利用了多态特性)完成解耦。
最后看一下客户端:
// 客户端(调用方)
public class client {
public static void main(String[] args){
// 用户召唤工厂
TransportFactory truckFactory = new TruckFactory();
TransportFactory airplaneFactory = new AirplaneFactory();
// 工厂为用户提供具体产品
Transport truck = truckFactory.createTransport();
Transport airplane = airplaneFactory.createTransport();
// 具体产品提供服务
truck.load(); // 卡车装货
truck.travel(); // 卡车运送
airplane.load(); // 飞机装货
airplane.travel(); // 飞机运送
}
}
工厂模式总结
- 只让客户“new工厂”,不让客户直接“new产品”(虽然客户实际上要的是产品)。
- 从客户端(调用方)代码看到,客户要做的只是利用两个具体工厂,“召唤”出了Truck和Airplane两个具体产品,并且“对照着说明书”完成了装货(load方法)和运送(travel方法)。至于Truck和Airplane是怎么生产出来的,load()和travel()是怎么实现的一概不用管(换个角度来看,对提供服务方也是一种保密)。
- 抽象产品和抽象工厂本身是接口还是抽象类,个人认为都可以。当然,如果抽象工厂类或抽象产品类内部有一些方法要实现或者包含一些类变量,就只能用抽象类了。
- 谁和谁解了耦?本人认为有两方面:1、客户和具体产品的实现细节解了耦;2、抽象工厂和具体产品解了耦。第一点就不多说了,而第二点保证了工厂模式的扩展性,需要扩展新产品时,“模板类”(本例中就是抽象产品类和抽象工厂类了)不需要做任何改动。解耦的实现,利用的是java中的继承特性。
共同学习,欢迎交流!
这里是源码demo