抽象工厂模式
简介
抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。根据里氏替换原则,任何接受父类型的地方,都应当能够接受子类型。因此,实际上系统所需要的,仅仅是类型与这些抽象产品角色相同的一些实例,而不是这些抽象产品的实例。换言之,也就是这些抽象产品的具体子类的实例。工厂类负责创建抽象产品的具体子类的实例。
意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
主要解决:主要解决接口选择的问题。
何时使用:系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
如何解决:在一个产品族里面,定义多个产品。
关键代码:在一个工厂里聚合多个同类产品。
应用实例:工作了,为了参加一些聚会,肯定有两套或多套衣服吧,比如说有商务装(成套,一系列具体产品)、时尚装(成套,一系列具体产品),甚至对于一个家庭来说,可能有商务女装、商务男装、时尚女装、时尚男装,这些也都是成套的,即一系列具体产品。假设一种情况(现实中是不存在的,要不然,没法进入共产主义了,但有利于说明抽象工厂模式),在您的家中,某一个衣柜(具体工厂)只能存放某一种这样的衣服(成套,一系列具体产品),每次拿这种成套的衣服时也自然要从这个衣柜中取出了。用 OO 的思想去理解,所有的衣柜(具体工厂)都是衣柜类的(抽象工厂)某一个,而每一件成套的衣服又包括具体的上衣(某一具体产品),裤子(某一具体产品),这些具体的上衣其实也都是上衣(抽象产品),具体的裤子也都是裤子(另一个抽象产品)。
优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。
使用场景: 1、QQ 换皮肤,一整套一起换。 2、生成不同操作系统的程序。
注意事项:产品族难扩展,产品等级易扩展。
类图
实现方式
这里使用服装作为示例,正式服装和休闲服装都包含了帽子,上衣和裤子,那么这里就包含了2个等级的产品(正式装(包括帽子,上衣和裤子)和休闲装(包括帽子,上衣和裤子))。在使用的时候应该是正式装的帽子上衣和裤子一起穿才是正确的,而不可以帽子(正式),上衣(正式),裤子(休闲)这样另类的搭配。抽象工厂模式就是解决这一类问题而出现的。
帽子抽象接口
package com.rabbit.pattern.abstract_factory;
/**
* 帽子抽象接口
* Created by vip on 2018/2/11.
*/
public interface Cap {
void execute();
}
正式帽子实现类
package com.rabbit.pattern.abstract_factory;
/**
* 正式装帽子
* Created by vip on 2018/2/11.
*/
public class OfficialCap implements Cap {
@Override
public void execute() {
System.out.println("正式装的帽子");
}
}
休闲帽子实现类
package com.rabbit.pattern.abstract_factory;
/**
* 休闲装的帽子
* Created by vip on 2018/2/11.
*/
public class RelaxationCap implements Cap {
@Override
public void execute() {
System.out.println("休闲装的帽子");
}
}
上衣抽象接口
package com.rabbit.pattern.abstract_factory;
/**
* 上衣抽象接口
* Created by vip on 2018/2/11.
*/
public interface Clothing {
void execute();
}
正式上衣实现类
package com.rabbit.pattern.abstract_factory;
/**
* 正式装的上衣
* Created by vip on 2018/2/11.
*/
public class OfficialClothing implements Clothing {
@Override
public void execute() {
System.out.println("正式装的上衣");
}
}
休闲上衣实现类
package com.rabbit.pattern.abstract_factory;
/**
* 休闲装的上衣
* Created by vip on 2018/2/11.
*/
public class RelaxationClothing implements Clothing {
@Override
public void execute() {
System.out.println("休闲装的上衣");
}
}
裤子抽象接口
package com.rabbit.pattern.abstract_factory;
/**
* 裤子抽象接口
* Created by vip on 2018/2/11.
*/
public interface Trousers {
void execute();
}
正式裤子实现类
package com.rabbit.pattern.abstract_factory;
/**
* 正式装的裤子
* Created by vip on 2018/2/11.
*/
public class OfficialTrousers implements Trousers {
@Override
public void execute() {
System.out.println("正式装的裤子");
}
}
休闲裤子实现类
package com.rabbit.pattern.abstract_factory;
/**
* 休闲装的裤子
* Created by vip on 2018/2/11.
*/
public class RelaxationTrousers implements Trousers {
@Override
public void execute() {
System.out.println("休闲装的裤子");
}
}
抽象工厂
抽象工厂中定义了系列产品应该包含哪些抽象工厂,例如下面包含了抽象帽子,抽象上衣,抽象裤子3个种类的工厂。具体的示例在子类中才知道是创建那个具体的实例对象。
package com.rabbit.pattern.abstract_factory;
/**
* 工厂类
* Created by vip on 2018/2/11.
*/
public interface SuitFactory {
Cap newCap();//抽象帽子
Clothing newClothing();//抽象上衣
Trousers newTrousers();//抽象裤子
}
正式装工厂
正式装的工厂实例化了具体的正式帽子,正式上衣,正式裤子类,实例化的都是正式的,这样在客户端调用的时候只需要调用对应的工厂即可,实例的都是合法的对象(帽子,上衣,裤子)等。
package com.rabbit.pattern.abstract_factory;
/**
* 正式装具体工厂
* Created by vip on 2018/2/11.
*/
public class OfficialSuitFactory implements SuitFactory {
@Override
public Cap newCap() {
return new OfficialCap();//创建正式装的帽子
}
@Override
public Clothing newClothing() {
return new OfficialClothing();//创建正式装的上衣
}
@Override
public Trousers newTrousers() {
return new OfficialTrousers();//创建正式装的裤子
}
}
休闲装工厂
休闲装的工厂实例化了具体的休闲帽子,休闲上衣,休闲裤子类,实例化的都是休闲的,这样在客户端调用的时候只需要调用对应的工厂即可,实例的都是合法的对象(帽子,上衣,裤子)等。
package com.rabbit.pattern.abstract_factory;
/**
* 休闲衣服工厂
* Created by vip on 2018/2/11.
*/
public class RelaxationSuitFactory implements SuitFactory {
@Override
public Cap newCap() {
return new RelaxationCap();//休闲的帽子
}
@Override
public Clothing newClothing() {
return new RelaxationClothing();//休闲的上衣
}
@Override
public Trousers newTrousers() {
return new RelaxationTrousers();//休闲的裤子
}
}
总结
工厂方法模式(http://blog.csdn.net/sinat_32366329/article/details/79293825)和抽象工厂模式很像,这也是很多初学者没有对比过无法理解的原因。工厂方法模式解决的是单一级别产品的对象创建工作,而抽象工厂模式解决的是多个级别的产品一系列的对象创建工作,例如:本次案例中的正式服装和休闲服装就是2个级别的产品,同时包含了一系列的对象(帽子,衣服,裤子)。这样可以确保实例化的对象都是一个级别的产品。工厂方法模式(可以参考博客地址http://blog.csdn.net/sinat_32366329/article/details/79293825)中的猫和狗属于动物类,都有自己的工厂方法创建对象,但是只有一个产品,就是猫或者狗,没有其他。
一句话总结:工厂方法模式支持一个抽象对象的创建,抽象工厂模式支持多个抽象对象的创建。
设计模式本没有好坏之分,只有合适自己的才是最好的。