抽象工厂模式

内容简介:简单的案例实现抽象工厂模式,分析抽象工厂的优势与存在的问题。

系列文章

单例模式

Build 模式

前言

简单工厂根据对象类型信息创建对象,但责任太重,不符合单一职责原则;工厂模式引入等级结构,解决了简单工厂责任太重的问题,那抽象工厂的主要作用是什么呢?

产品等级结构和产品簇

如果要区分工厂和抽象工厂,理解产品等级结构和产品簇是必要条件。 

640?wx_fmt=jpeg

图片引自:https://www.cnblogs.com/lfxiao/p/6811820.html

上图展示了产品等级和产品簇之间的区别。

在横坐标方向,图形分正方形,原型,椭圆;在纵坐标方向上,为每种图形的不同颜色。产品等级结构是相同产品的不同表现形式,比如车->黑色的车->白色的车,在产品等级结构中,所有的产品都有共同的基类;产品簇是具有某种相同属性的不同产品,比如黑色的宝马车->黑色的自行车->黑色的手扶拖拉机,在产品簇中,所有的产品拥有相同的约束--黑色的车。

定义

为创建一组或具有相同约束的对象提供一个接口。

适用范围

一个产品由相同的约束。比如都是黑色的交通工具,都是黑色的图形......

实现

在介绍工厂模式时,使用的示例如下: 

640?wx_fmt=png工厂的基类 Factory 定义了createAnimal 方法,具体的工厂根据待生产的产品的不同分 CatFactory 和 DogFactory ,这两个 Factory 的子类分别用于新建 Cat 对象和 Dog 对象。

假设现在对猫 Animal 进行具体化,分为黑颜色的猫 BlackCat ,白颜色的猫 WhiteCat ,黑颜色的狗 BlackDog ,白颜色的狗 WhiteDog ,如果使用工厂模式,结构图如下: 

640?wx_fmt=png

可以发现系统中的类会成对增加,造成这种情况的原因在于每个工厂只能生产一种具体的产品,每增加一个产品均需要新建一个工厂,那有没有什么方法能够避免这种情况的出现呢?

在以上的示例中,白色的狗 WhiteDog 和白色的猫 WhiteCat 都是相同颜色的动物,相同颜色的狗和猫是相同颜色的小动物,将他们放在同一个产品簇中,修改后的结构如下: 

640?wx_fmt=png

如果继续添加黑色的猪 BlackPig ,白色的猪 WhitePig ,则只需要增加新的 Animal 类型,在 Factory 中添加对应的 create 方法即可,不会出现类急剧增多的情况。

具体实现如下:

public interface Animal {	
    void eat();	
}

public class Cat implements Animal {	
    private String color;	
    public Cat(String color) {	
        // TODO Auto-generated constructor stub	
        this.color = color;	
    }	
    @Override	
    public void eat() {	
        // TODO Auto-generated method stub	
        System.out.println(color + " cat eats");	
    }	
}

public class Dog implements Animal {	
    private String color;	
    public Dog(String color) {	
        // TODO Auto-generated constructor stub	
        this.color = color;	
    }	
    @Override	
    public void eat() {	
        // TODO Auto-generated method stub	
        System.out.println(color + " dog eats");	
    }	
}

public abstract class AbstractAnimalFactory {	
    abstract Animal makeCat();	
    abstract Animal makeDog();	
}

public class BlackAnimalFactory extends AbstractAnimalFactory {	
    @Override	
    Animal makeCat() {	
        // TODO Auto-generated method stub	
        return new Cat("black");	
    }	
    @Override	
    Animal makeDog() {	
        // TODO Auto-generated method stub	
        return new Dog("black");	
    }	
}

public class WhiteAnimalFactory extends AbstractAnimalFactory {	
    @Override	
    Animal makeCat() {	
        // TODO Auto-generated method stub	
        return new Cat("white");	
    }	
    @Override	
    Animal makeDog() {	
        // TODO Auto-generated method stub	
        return new Dog("white");	
    }	
}

测试代码如下:

public static void main(String [] args) {	
        AbstractAnimalFactory whiteAnimalFactory = new WhiteAnimalFactory();	
        Cat whiteCat = (Cat) whiteAnimalFactory.makeCat();	
        Dog whiteDog = (Dog) whiteAnimalFactory.makeDog();	
        whiteCat.eat();	
        whiteDog.eat();	
        AbstractAnimalFactory blackAnimalFactory = new BlackAnimalFactory();	
        Cat blackCat = (Cat) blackAnimalFactory.makeCat();	
        Dog blackDog = (Dog) blackAnimalFactory.makeDog();	
        blackCat.eat();	
        blackDog.eat();	
    }

运行结果如下:

white cat eatswhite dog eatsblack cat eatsblack dog eats

问题

似乎抽象工厂很完美,现在有一个新的需求过来了,需要在系统中添加白色的猪 WhitePig 和黑色的猪 BlackPig 。突然发现在原有的抽象工厂结构中,如果需要添加这两种 Animal ,需要对 Factory 进行修改,添加 makePig 方法,同时 WhiteAnimalFactory 和 BlackAnimalFactory 都需要实现 makePig 方法。

这样的设计违反了开闭原则(一个软件实体应当对扩展开放,对修改关闭),有没有什么办法解决这个问题呢?抽象工厂无法解决这样的问题。可以发现,使用抽象工厂时,增加产品簇(在本文中可以理解为为现有动物添加新的颜色分类)可以满足开闭原则,但是增加产品等级结构(在本文中可以理解为增加新的动物),就需要对原结构进行大量的修改。

总结

  • 简单工厂侧重根据类型信息创建对象,但是不符合单一职责原则;工厂模式中每个工厂只生产一种具体的产品,如果产品过多,可能会导致系统中存在大量的工厂类;抽象工厂将工厂模式中相关的产品组成产品簇,由一个工厂生产,减少了系统中类的数量。

  • 使用抽象工厂增加产品簇符合开闭原则,但增加产品等级结构不满足开闭原则。

  • 在使用抽象工厂模式之前,需要设计好产品簇和产品等级结构,防止由于增加产品等级结构而造成系统大幅度的改动。

--END--

识别二维码,关注我们

640?wx_fmt=png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值