工厂模式
概述
在平时编码过程中,当需要一个新对象的时候,我们第一反应就是直接new一个对象出来。以下用买车来举个例子。
Car porsche= new Porsche();
Car ferrari = new Ferrai();
.
.
.
那么,如果一个完整的购车流程就会变成以下这样:
public Car buyCar(String type){
Car car = null;
createOrder();
prepare();
if (type.equals("Ferrai")){
car = new Ferrai();
}else if (type.equals("Porsche")){
car = new Porsche();
}
signContract();
pay();
return car;
}
而这样的结果就造成了,如果我每次有个新品牌的车进来,那就需要修改这个下单的流程。另外还有一点,这个方法的目的是为了买车,但是却将创建新车的逻辑功能加入到其中,把不同的业务逻辑耦合到一起了。这就违反了设计原则中的单一职责原则(每个类只负责单一的功能)。
简单工厂模式
首先将创建车的逻辑剥离出来,新建一个简单工厂类来根据类型创建对象
public class SimpleFactory {
Car createCar(String type){
Car car = null;
if (type.equals("Ferrai")){
car = new Ferrai();
}else if (type.equals("Porsche")){
car = new Porsche();
}
return car;
}
}
原来的方法就改为
public Car buyCar(String type){
Car car = null;
createOrder();
prepare();
car = createCar(type);
signContract();
pay();
return car;
}
上面SimpleFactory就被称为 简单工厂,简单工厂模式是由一个工厂对象来决定创建出哪一种对象实例。
虽然以上改动很简单,但是这个简单工厂里的代码就是可以复用的了,因为创建车这个行为不仅仅是用户买车的时候需要,也有可能是车商会需要这个接口。总之,创建车这个行为在抽取出来之后,就可以在任何需要的地方调用,而修改的时候也仅需要修改这个工厂的逻辑。
下图就是简单工程模式的类图,来自百度百科。
工厂模式
上面举了个简单的造车厂的例子,来解释何为简单工厂模式,但是在实际生活中呢,我们要去4s店买车的时候,不同品牌的汽车都是由不同的主机厂生产的。
对于不同的主机厂,生产车的技术流程都是不同的,但是对于我们买车的人来说,其他步骤是一样的:创建订单,签合同,付钱,开走。
因此,我们将相同的逻辑提取出来,如下。
public abstract class CarStore {
public Car buyCar(String type){
Car car = null;
createOrder();
prepare();
//由子类实现
car = createCar(type);
signContract();
pay();
return car;
}
protected abstract Car createCar(String type);
// 其他方法
}
然后不同的车商继承这个类,并实现自己的造车方法
public class FerraiCarStore extends CarStore {
@Override
protected Car createCar(String type) {
if ("Cayenne".equals(type))
return new Cayenne();
if ("Macan".equals(type))
return new Macan();
}
}
这就是工厂模式:定义一个创建对象的接口,由子类来决定实例化的对象是哪一个(如上面这个例子,我想买Cayenne就传个Cayenne,想买Macan就传个Macan进去,然后等着交钱开车就好了)。
工厂模式的好处就是将客户端和具体的产品解耦了,当我们需要一个产品来为我们服务的时候,但是这个产品有不同的实现(比如不同的数据库),就可以用工厂模式了。
以下就是工厂模式的类图:
抽象工厂模式
主机厂在造车之前,必须获得各种原材料才可以生产汽车。造车厂无需关心材料来自何处,你只要给我能用的,质量合格的材料,我就可以生产出客户需要的汽车。所以我们可以这样改造主机厂。
public class FerraiCarStore extends CarStore {
MateraialFactory materaialFactory;
@Override
protected Car createCar(String type) {
prepareMaterial();
if ("Cayenne".equals(type))
return new Cayenne();
if ("Macan".equals(type))
return new Macan();
return null;
}
public void prepareMaterial(){
steel = materaialFactory.getSteel();
plastic = materaialFactory.getPlastic();
}
}
材料工厂
public interface MateraialFactory {
void getSteel();
void getPlastic();
}
这样,我们就可以选择材料厂商了,工厂就只知道如何用材料造车,而无需关心原料来源。
这就是抽象工厂模式,定义:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。