-
简单工厂
场景描述
假如我们有一家店来卖多种型号车,不同客户根据需求购买不同型号车。
实现方式
用简单工厂模式来实现时,我们创建一个接口,不同型号的车实现这个接口。
接下来创建一个工厂类,客户委托工厂类来创建不同型号的车。
类图
具体实现
步骤1:
创建一个产品类接口
interface Car{
void getType();
}
步骤2:创建实现接口的实现类
class CarA implements Car{
@Override
public void getType(){
System.out.println("我是型号A");
}
}
class CarB implements Car{
@Override
public void getType() {
System.out.println("我是型号B");
}
}
class CarC implements Car{
@Override
public void getType() {
System.out.println("我是型号C");
}
}
步骤3:创建工厂类
class SimpleFactory{
public static final int CARA = 1;
public static final int CARB = 2;
public static final int CARC = 3;
public static Car getCar(int type){
Car c = null;
switch (type){
case CARA:
c = new CarA();
break;
case CARB:
c = new CarB();
break;
case CARC:
c = new CarC();
break;
}
return c;
}
}
步骤4:客户需求
public class SimpleFactoryTest {
public static void main(String[] args) {
SimpleFactory.getCar(SimpleFactory.CARA).getType();
SimpleFactory.getCar(SimpleFactory.CARB).getType();
SimpleFactory.getCar(SimpleFactory.CARC).getType();
}
}
输出结果:
我是型号A
我是型号B
我是型号C
优点:
简单工厂方法包含从一个类的结构中选择初始类的业务逻辑。
简单工厂实现了责任分离,客户类不直接创建产品类的对象,客户只作为对象的消费者,因此当客户创建复杂对象时,通过调用工厂类。减少客户的负担。从这里也可知道,简单类并不需要工厂模式。
缺点:
由类图可以看出,工厂类需要知道怎样创建每个子类的对象,所以每当增加产品类时,都需要修改工厂类的代码。简单工厂方法模式不符合开闭原则。
-
工厂方法
场景描述
假如我们卖多种型号车,不同客户根据需求购买不同型号车。那么我们可以开一家总店,旗下有多家子店,不同的子店卖不同型号车。总店不卖车,但客户可以通过总店获取子店。
实现方式
用工厂模式来实现时,我们创建一个接口,不同型号的车(产品类)实现这个接口。
接下来创建一个接口(总店),不同的工厂类(子店)实现这个结构。
客户委托工厂类来创建不同型号的车。
类图
具体实现
步骤1:创建产品类接口
见简单工厂具体实现
步骤2:创建实现产品类接口的产品类
见简单工厂具体实现
步骤3:创建工厂类接口
interface CarFactory{
Car getCar();
}
步骤4:创建实现工厂类接口的工厂类
class FactoryA implements CarFactory{
@Override
public Car getCar() {
return new CarA();
}
}
class FactoryB implements CarFactory{
@Override
public Car getCar() {
return new CarB();
}
}
class FactoryC implements CarFactory{
@Override
public Car getCar() {
return new CarC();
}
}
步骤5:客户需求
public class FactoryTest {
public static void main(String[] args) {
new FactoryA().getCar().getType();
new FactoryB().getCar().getType();
new FactoryC().getCar().getType();
}
}
输出结果:
我是型号A
我是型号B
我是型号C
优点:
在简单工厂模式中,如果要增加一个新产品类,相应的要修改工厂类代码,但在工厂模式中,如果要增加一个新产品类,只需要继承工厂接口和产品接口,不需要修改其他类代码结构。因此工厂模式支持开闭原则。
缺点:
但在上述场景描述中,如果我不只是卖车,还卖车轮胎。车有不同型号,相对应的车轮胎也有不同型号。再如小米工厂与华为工厂,这两家工厂不仅生产键盘,也生产鼠标。这时工厂模式就不够用了。因此也有了抽象工厂。
-
抽象工厂
先来认识下什么是产品族:位于不同产品等级结构中,功能相关联的产品组成的家族。
例如上述例子中,我家店不只卖车,也卖轮胎,其中车型号A和轮胎型号A为一个产品族,车型号B和轮胎型号B为一个产品族。又如小米工厂和华为工厂,小米和华为都生产键盘和鼠标,其中小米鼠标和小米键盘为一个产品族,因为都是小米产的。同样的,华为键盘和华为鼠标为一个产品族
回到抽象产品模式的话题上,可以这么说,它和工厂方法模式的区别就在于需要创建对象的复杂程度上。而且抽象工厂模式是三个里面最为抽象、最具一般性的。抽象工厂模式的用意为:给客户端提供一个接口,可以创建多个产品族中的产品对象。而且使用抽象工厂模式还要满足一下条件:
1.系统中有多个产品族,而系统一次只可能消费其中一族产品
2.同属于同一个产品族的产品一起使用时。
来看看抽象工厂模式的各个角色(和工厂方法的如出一辙):
抽象工厂角色:这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。
具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。在java中它由具体的类来实现。
抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。
具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。
摘自:http://www.cnblogs.com/poissonnotes/archive/2010/12/01/1893871.html
场景描述
厂商不仅卖不同型号的车,还卖轮胎
类图
具体实现
步骤1:创建产品类接口
车见简单工厂具体实现
interface Tyre{
void getType();
}
步骤2:创建实现产品类接口的产品类
车见简单工厂具体实现
class TyreA implements Tyre {
@Override
public void getType() {
System.out.println("我是轮胎A");
}
}
class TyreB implements Tyre {
@Override
public void getType() {
System.out.println("我是轮胎B");
}
}
步骤3:创建抽象工厂类
abstract class AbstractFactory {
abstract public Car getCar();
abstract public Tyre getTyre();
}
步骤4:创建具体工厂类
class FactoryOne extends AbstractFactory{
@Override
public Car getCar() {
return new CarA();
}
@Override
public Tyre getTyre() {
return new TyreA();
}
}
class FactoryTwo extends AbstractFactory{
@Override
public Car getCar() {
return new CarB();
}
@Override
public Tyre getTyre() {
return new TyreB();
}
}
步骤5:创建一个工厂创造器/生成器类 FactoryProducer
class FactoryProducer{
public static AbstractFactory createFactoryOne(){
return new FactoryOne();
}
public static AbstractFactory createFactoryTwo(){
return new FactoryTwo();
}
}
步骤6:客户需求
public class AbstractFactoryTest {
public static void main(String[] args) {
AbstractFactory af = FactoryProducer.createFactoryOne();
af.getCar().getType();
af.getTyre().getType();
af = FactoryProducer.createFactoryTwo();
af.getCar().getType();
af.getTyre().getType();
}
}
输出结果
我是型号A
我是轮胎A
我是型号B
我是轮胎B
优点:
当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象
缺点:
当更改需求时,如果是增加一个产品族,例如增加一个工厂卖车型号C,轮胎型号C,则只要增加相应的工厂子类即可,对原有的产品类代码与共产类代码不产生任何影响。符合开闭原则。
但如果是增加一个新产品时,则必须在每个工厂实类中增加具体方法。例如增加出售车门。在此情况下,抽象工厂不符合开闭原则