设计模式——抽象工厂
1.抽象工厂
什么是抽象工厂?简单的来说,抽象工厂是对具体工厂的抽象,它只负责产品的创建,并不负责产品的具体实现,而产品的具体实现是由实现该抽象工厂的具体工厂来完成。
2.举例:电子产品工厂
就拿我们常见的电子产品来做一个抽象工厂的讲解,生活中常见的电子品牌有苹果、小米、华为、魅族等,它们都有自己许多种类相似的产品,如苹果有苹果手机、苹果平板、苹果耳机等等,小米也有小米手机、小米平板、小米耳机等等。
抽象其实就是把一类事物的共性抽取出去,上面的例子,苹果和小米都能创建手机、平板、耳机这一系列有共同特征的产品。在定义的时候就说过,抽象工厂只负责产品的创建。也就是说这几个产品都可以由抽象工厂创建。
那我们就可以写一个抽象工厂的接口,代码如下。
//电子产品工厂
public interface ElectronicProductFactory {
public Phone getPhone();
public Headset getHeadset();
}
这里只创建了两个产品,一个是耳机,一个是手机,当然还有其它相似的产品,就不在这里一一写了。
在定义的时候还说过,产品的具体创建是交给具体工厂完成的,现在我们有两个厂商(小米、苹果)那么也就应该有两个具体工厂,分别负责创建属于自己品牌的产品,代码如下。
//苹果工厂 只负责创建苹果的产品
public class AppleFactory implements ElectronicProductFactory{
@Override
public Phone getPhone() {
return new ApplePhone();
}
@Override
public Headset getHeadset() {
return new AppleHeadset();
}
}
//小米工厂 只负责创建小米的产品
public class XiaoMiFactory implements ElectronicProductFactory {
@Override
public Phone getPhone() {
return new XiaoMiPhone();
}
@Override
public Headset getHeadset() {
return new XiaoMiHeadset();
}
}
好,现在我们有了具体的工厂,但是我们还没有具体的产品,那么我们就可以创建具体的产品了,首先是对手机的抽象,手机都有很多共有的属性,如有系统,有CPU,有外观等等,手机还有很多共同的方法(行为),如打电话、上网、拍照等等。耳机也有许多共有的属性,如类型、外观、音质等等,耳机共同的方法(行为),如听歌、调音量等等。
先看对手机的抽象,代码如下。
//我是手机
public abstract class Phone {
//处理器
private String cpu;
public abstract void call();
public abstract void takePictures();
public String getCpu() {
return cpu;
}
public void setCpu(String cpu) {
this.cpu = cpu;
}
}
再看对耳机的抽象,代码如下。
//我是耳机
public abstract class Headset {
//音质
private String timbre;
public abstract void listenMusic();
public String getTimbre() {
return timbre;
}
public void setTimbre(String timbre) {
this.timbre = timbre;
}
}
因为内容较多,我就只写一两个属性。然后是每个产品的具体实现,如小米耳机,苹果耳机,小米手机,苹果手机等。代码如下,很容易理解,就不多说了。
//苹果手机的具体实现
public class ApplePhone extends Phone {
public ApplePhone() {
setCpu("A系列CPU!");
}
@Override
public void call() {
System.out.println("我是苹果手机,我能打电话!");
}
@Override
public void takePictures() {
System.out.println("我是苹果手机,我拍照好!");
}
}
//小米手机的具体实现
public class XiaoMiPhone extends Phone {
public XiaoMiPhone() {
setCpu("高通系列CPU");
}
@Override
public void call() {
System.out.println("我是小米手机,我也能打电话!");
}
@Override
public void takePictures() {
System.out.println("我是小米手机,我拍照也还可以!");
}
}
//苹果耳机的具体实现
public class AppleHeadset extends Headset {
public AppleHeadset() {
setTimbre("nice");
}
@Override
public void listenMusic() {
System.out.println("我是苹果耳机,比较高档,听歌很舒服!");
}
}
//小米耳机的具体实现
public class XiaoMiHeadset extends Headset {
public XiaoMiHeadset() {
setTimbre("good");
}
@Override
public void listenMusic() {
System.out.println("我是小米耳机,能听歌!");
}
}
工厂和产品都已经创建完毕,下面就去测试一下我们的抽象工厂。
public class Main {
public static void main(String [] args) {
//创建一个苹果工厂,只生产苹果的产品。
ElectronicProductFactory electronicProductFactory = new AppleFactory();
//拿到一个手机
Phone phone = electronicProductFactory.getPhone();
System.out.println("处理器用的是"+phone.getCpu());
phone.call();
phone.takePictures();
//拿到一个耳机
Headset headset = electronicProductFactory.getHeadset();
System.out.println("音质是:"+headset.getTimbre());
headset.listenMusic();
}
}
//打印结果
处理器用的是A系列CPU!
我是苹果手机,我能打电话!
我是苹果手机,我拍照好!
音质是:nice
我是苹果耳机,比较高档,听歌很舒服!
3.总结
从上面代码可以看出,工厂使用的是抽象的工厂,而产品也是使用的是抽象类,说到这里你应该明白了吧,抽象工厂不仅是要对具体工厂进行抽象,也需要对产品进行抽象。
抽象工厂和简单工厂以及工厂方法模式不太相同,因为简单工厂和工厂方法模式都是只创建一类产品,如要么只创建手机,要么只创建耳机。而抽象工厂是对一系列产品的创建(产品族),它是工厂的工厂,抽象工厂负责定义创建的产品,而具体工厂是该类的产品(如苹果工厂负责创建苹果的产品,小米工厂负责创建小米的产品)。
写了这么多,如果你还是不太清楚抽象工厂,那么请仿着上面的代码敲一遍。
大家有没有想过抽象工厂有什么缺点?我们在定义抽象工厂的时候,是定义创建的产品,就算我们能创建出目前已知的所有产品,如果某天又有了新的产品,假设某天有了个人飞行设备。那么我们就得去修改抽象工厂的接口方法,新增一个个人飞行设备的创建,这样就很明显的违背了开闭原则。
抽象工厂模式主要是用来解决产品族的创建,也就是上面的某个厂商一系列的产品,好了就写这么多了,大家慢慢消化。