Android设计模式(3)——抽象工厂模式

818 阅读6分钟

抽象工厂模式的定义

为创建一组相关的或相互依赖的对象提供一个接口,而且无需指定他们的具体类

抽象工厂模式的通用类图

抽象工厂模式是工厂方法模式的升级产品,在有多个业务品种,业务分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式。

抽象工厂模式通用源代码类图

首先由两个互相影响的产品线(也叫产品族),例如制造汽车的左侧车门和右侧车门,这两个应该是数量相等的----两个对象间的约束,每个型号的车门是不一样的,这是产品等级的结构约束。 下面看下源码实现:

抽象产品类A

package com.zxf.srp.factory3;

public abstract class AbstractProductA {
    //每个产品都公有的方法
    public void shardMethod(){}

    //没个产品相同方法,不同的实现
    public abstract void doSomething();
}

产品A1的实现

public class ProductA1 extends AbstractProductA {

    @Override
    public void doSomething() {
        System.out.println("产品A1的实现方法");
    }
}

产品A2的实现

public class ProductA2 extends AbstractProductA {

    @Override
    public void doSomething() {
        System.out.println("产品A2的实现方法");
    }
}

抽象产品类B

public abstract class AbstractProductB {
    //每个产品都公有的方法
    public void shardMethod(){}

    //没个产品相同方法,不同的实现
    public abstract void doSomething();
}

产品B1的实现

public class ProductB1 extends AbstractProductB {

    @Override
    public void doSomething() {
        System.out.println("产品B1的实现方法");
    }
}

产品B2的实现

public class ProductB2 extends AbstractProductB {

    @Override
    public void doSomething() {
        System.out.println("产品B2的实现方法");
    }
}

抽象工厂类的职责是定义每个工厂要实现的功能,在通用代码中,抽象工厂定义了两个产品族的产品创建。

抽象工厂类

public abstract class AbstractCreator {
    //创建A产品家族
    public abstract AbstractProductA createProductA();
    //创建B产品家族
    public abstract AbstractProductB createProductB();
}

如何创建一个产品,则是由具体的实现类来完成的。

产品等级1的实现类

public class Creator1 extends AbstractCreator {
    @Override
    public AbstractProductA createProductA() {
        return new ProductA1();
    }

    @Override
    public AbstractProductB createProductB() {
        return new ProductB1();
    }
}

产品等级2的实现类

public class Creator1 extends AbstractCreator {
    @Override
    public AbstractProductA createProductA() {
        return new ProductA2();
    }

    @Override
    public AbstractProductB createProductB() {
        return new ProductB2();
    }
}

注意:有M个产品等级就应该有M个实现类工厂,在每个实现工厂中。实现不同产品组的生产任务

场景类

public class Client {
    public static void main(String[] args){
        //定义出两个工厂
        AbstractCreator creator1 = new Creator1();
        AbstractCreator creator2 = new Creator2();

        //产生1级对象
        AbstractProductA productA1 = creator1.createProductA();
        AbstractProductB productB1 = creator1.createProductB();

        //产生2级对象
        AbstractProductA productA2 = creator1.createProductA();
        AbstractProductB productB2 = creator1.createProductB();
    }
}

在场景类类中,没有一个方法与实现类有关系,对于一个产品来说,我们只要知道它的工厂方法就可以直接产生一个产品对象,无需关心他的实现类。

具体的实例

我们改造之前的女娲的例子,女娲造人需要区分男女。下面是类图:

这个类图虽然大,但是比较简单,一个接口,多个抽象类,然后是N个实现类,每一个人中都是抽象类,性别是在个各自的实现类中实现的,HumanFactory接口中定义了三个方法,别分用来生产三个不同肤色的人中。

代码示例如下:

/**
 * 人类接口
 */
public interface Human {
    /**
     * 不同的肤色
     */
    public void getColor();

    /**
     * 不同的语言
     */
    public void getLanguage();

    /**
     * 不同的性别
     */
    public void getSex();
}
/**
 * 白种人
 */
public abstract class AbstractWhiteHuman implements Human {
    @Override
    public void getColor() {
        System.out.println("白种人皮肤是白色的");
    }

    @Override
    public void getLanguage() {
        System.out.println("白种人说英语");
    }
}
/**
 * 黑种人
 */
public abstract class AbstractBlackHuman implements Human {
    @Override
    public void getColor() {
        System.out.println("黑种人皮肤是黑色的");
    }

    @Override
    public void getLanguage() {
        System.out.println("黑种人说南非语");
    }
}
/**
 * 黄种人
 */
public abstract class AbstractYellowHuman implements Human {
    @Override
    public void getColor() {
        System.out.println("黄种人皮肤是黄色的");
    }

    @Override
    public void getLanguage() {
        System.out.println("黄种人说汉语");
    }
}

每个抽象类都有两个实现类,分别实现公共的最细节,最具体的事物。

/**
 * 黄种人女性
 */
public class FemaleYellowHuman extends AbstractYellowHuman {
    @Override
    public void getSex() {
        System.out.println("黄种人女性");
    }
}
/**
 * 黄种人男性
 */
public class MaleYellowHuman extends AbstractYellowHuman {
    @Override
    public void getSex() {
        System.out.println("黄种人男性");
    }
}

白种人和黑种人的具体实现跟黄种人一样,就省略了。

/**
 * 人类创建工厂类
 */
public interface HumanFactory {
    //制造一个黄种人
    public Human createYellowHuman();
    //制造一个白种人
    public Human createWhiteHuman();
    //制造一个黑种人
    public Human createBlackHuman();
}

在接口中,我们是可以生产出不同肤色人种的,具体生产那种性别的人,需要下面去具体工厂去实现。

/**
 * 女性制造工厂
 */
public class FemaleFactory implements HumanFactory {

	//创建黄种人女性
    @Override
    public Human createYellowHuman() {
        return new FemaleYellowHuman();
    }
	
    //创建白种人女性
    @Override
    public Human createWhiteHuman() {
        return new FemaleWhiteHuman();
    }
	
    //创建黑种人女性
    @Override
    public Human createBlackHuman() {
        return new FemaleBlackHuman();
    }
}
/**
 * 男性制造工厂
 */
public class MaleFactory implements HumanFactory {

    //创建黄种人男性
    @Override
    public Human createYellowHuman() {
        return new MaleYellowHuman();
    }

    //创建白种人男性
    @Override
    public Human createWhiteHuman() {
        return new MaleWhiteHuman();
    }

    //创建黑种人男性
    @Override
    public Human createBlackHuman() {
        return new MaleBlackHuman();
    }
}
/**
 * 场景类
 */
public class NvWa {
    public static void main(String[] args){
        //第一条生产线
        HumanFactory maleFactory = new MaleFactory();
        //第二条生产线
        HumanFactory femaleFactory = new FemaleFactory();

        //生产线建立完毕,开始生产人
        Human yellowMaleHuman = maleFactory.createYellowHuman();
        Human yellowFemaleHuman = femaleFactory.createYellowHuman();

        System.out.println("----生产一个黄种人女性-----");
        yellowFemaleHuman.getColor();
        yellowFemaleHuman.getLanguage();
        yellowFemaleHuman.getSex();
        System.out.println("----生产一个黄种人男性-----");
        yellowMaleHuman.getColor();
        yellowMaleHuman.getLanguage();
        yellowMaleHuman.getSex();
    }
}
结果:
----生产一个黄种人女性-----
黄种人皮肤是黄色的
黄种人说汉语
黄种人女性
----生产一个黄种人男性-----
黄种人皮肤是黄色的
黄种人说汉语
黄种人男性

各种肤色的男性和女性都制造出来了,男性制造工厂只生产男性,女性制造工厂只生成女性,以后增加性别就很简单了,在创建一个工厂生产就行了。

抽象工厂的应用

抽象工厂模式的有点

1.封装性,每个产品的实现类不是高层模块要关心的,它关心的是接口,是抽象。对象是由工厂类制造出来的,我们只要知道工厂类是谁,就能创造出一个需要的对象。 2.产品族内的约束为非公开状态。例如生产男女比例的问题上,就应该有这样一个约束,每生产一个女性,就生产出一个男性,这样的生产过程对调用工厂的高层模块来说是透明的,他不需要知道这个约束。

抽象工厂模式的缺点

1.抽象工厂模式的最大缺点是产品族扩展非常困难,我们以通用代码为例,如果要增加一个产品C,也就是产品家族由原来的2个增加到3个,抽象类AbstractCreatoryao 增加一个方法,createProductC(),然后两个实现类都要修改,这严重违反了开闭原则。

抽象工厂的使用场景

抽象工厂模式的使用场景非常简单,一个对象族都有相同的约束,则可以使用抽象工厂模式,

抽象工厂的注意事项

抽象工厂模式的扩展比较困难,但是一定要清楚,是扩展产品族困难,而不是扩展产品等级困难,以上面的例子来说,增加一个肤色和困难,而增加一个性别很简单。

特别感谢

《设计模式之禅》

PS:觉得文章不还错的话可以添加公众号关注下,文章都会同步到公众号。