工厂模式[3] 抽象工厂 Abstract Factory

时间:2024-06-02 08:03:37

简介
1、简单工厂,或静态工厂,产品接口
  • 定义:专门定义一个类来负责创建其他类的实例,被创建的实例通常具有共同的父类或实现同一接口
  • 优点:客户端可以直接消费产品,而不必关心具体产品的实现(不关心对象的构造方法是怎么new的),消除了客户端直接创建产品对象的责任,实现了对责任的分割。
  • 缺点:工厂类记录了所有产品的创建逻辑,一旦不能正常工作,整个系统都会受到影响;而且当产品种类多、结构复杂的时候,把所有创建工作放进一个工厂中来,会使后期程序的扩展较为困难。
2、工厂方法,工厂接口+产品接口
  • 定义:在简单工厂的基础上,为工厂类定义了工厂接口,让其子类决定实例化哪个产品类。
  • 优点:简单工厂是把创建产品的职能都全部放在一个类里面,而工厂方法则是把不同的产品放在实现了工厂接口的不同工厂类里面,分割了工厂类的职能。
3、抽象工厂
  • 定义:抽象工厂提供一个固定的接口,用于创建一系列由关联或者相依存的对象,而不必指定其具体类或其创建的细节
工厂方法用来创建一个产品,它没有分类的概念,而抽象工厂则用于创建一系列产品,所以产品分类成了抽象工厂的重点。

工厂方法:一抽象产品类派生出多个具体产品类;一抽象工厂类派生出多个具体工厂类;【每个】具体工厂类只能创建【一个】具体产品类的实例。
即定义一个创建对象的接口(即抽象工厂类),让其子类(具体工厂类)决定实例化哪一个类(具体产品类)。【一对一】的关系。

抽象工厂:多个抽象产品类,派生出多个具体产品类;一个抽象工厂类,派生出多个具体工厂类;【每个】具体工厂类可创建【多个】具体产品类的实例。
即提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们的具体的类。【一对多】的关系。

抽象工厂

先修改人类定义的接口
/**
 * 定义一个人类的统称,问题出来了,刚刚定义的时候忘记定义性别了,这个重要的问题非修改不可,否则这个世界上太多太多的东西不存在了
 */
public interface IHuman {
    public void talk();
    //定义性别,注意,这个是用来给人类【分类】的,在抽象工厂中,很重要的一步就是合理的分类
    public void sex();
}

人类的接口定义好,然后根据接口创建两个抽象类,也就是两个【产品等级】,其实,抽象类的目的就是不允许你 new。
public abstract class AbstractWhiteHuman implements IHuman {
    @Override
    public void talk() {
        System.out.println("白色人种会说English");
    }
}
public abstract class AbstractYellowHuman implements IHuman {
    @Override
    public void talk() {
        System.out.println("黄种人会说汉语");
    }
}

然后就是些实现类了
public class YellowFemaleHuman extends AbstractYellowHuman {
    @Override
    public void sex() {
        System.out.println("女性黄种人");
    }
}
public class YellowMaleHuman extends AbstractYellowHuman {
    public void sex() {
        System.out.println("男行黄种人");
    }
}

抽象工厂模式下的【产品等级】和【产品族】都已经完成,下一步就等着工厂开工创建了,那我们来看工厂类。
在看工厂类之前我们先看那个枚举类型
public enum HumanEnum {
    //把世界上所有人类型都定义出来
    YelloMaleHuman("AbstractFactory.YellowMaleHuman"), YelloFemaleHuman("AbstractFactory.YellowFemaleHuman"), //
    WhiteFemaleHuman("AbstractFactory.WhiteFemaleHuman"), WhiteMaleHuman("AbstractFactory.WhiteMaleHuman");
    private String value="";
    //定义构造函数,目的是Data(value)类型的相匹配
    private HumanEnum(String value) {
        this.value = value;
    }
    public String getValue() {
        return this.value;
    }
}

然后,我们看我们的工厂类,先看接口
/**
 * 定一个烤箱,泥巴塞进去,人就出来
 */
public interface IHumanFactory {
    //制造黄色人种
    public IHuman createYellowHuman();
    //制造一个白色人种
    public IHuman createWhiteHuman();
}

然后看工厂的抽象类
public abstract class AbstractHumanFactory implements IHumanFactory {
    //给定一个性别人种,创建一个人类出来 专业术语是产生产品等级
    protected IHuman createHuman(HumanEnum humanEnum) {
        IHuman human = null;
        if (!humanEnum.getValue().equals("")) {//如果传递进来不是一个Enum中具体的一个Element的话,则不处理
            try {
                human = (IHuman) Class.forName(humanEnum.getValue()).newInstance();//直接产生一个实例
            } catch (Exception e) {//因为使用了enum,这个种异常情况不会产生了,除非你的enum有问题;
                e.printStackTrace();
            }
        }
        return human;
    }
}
看到没,这就是引入 enum 的好处,createHuman(HumanEnum humanEnum)这个方法定义了输入参数必须是 HumanEnum 类型,然后直接使用 humanEnum.getValue()方法就能获得具体传递进来的值。
这个抽象类的目的就是减少下边实现类的代码量。

我们看实现类
/**
 * 男性创建工厂,只创建男性
 */
public class MaleHumanFactory extends AbstractHumanFactory {
    //创建一个男性白种人
    @Override
    public IHuman createWhiteHuman() {
        return super.createHuman(HumanEnum.WhiteMaleHuman);
    }
    //创建一个男性黄种人
    @Override
    public IHuman createYellowHuman() {
        return super.createHuman(HumanEnum.YelloMaleHuman);
    }
}
/**
 * 女性创建工厂,只创建女性
 */
public class FemaleHumanFactory extends AbstractHumanFactory {
    //创建一个女性白种人
    @Override
    public IHuman createWhiteHuman() {
        return super.createHuman(HumanEnum.WhiteFemaleHuman);
    }
    //创建一个女性黄种人\
    @Override
    public IHuman createYellowHuman() {
        return super.createHuman(HumanEnum.YelloFemaleHuman);
    }
}

产品定义好了,工厂也定义好了,万事俱备只欠东风,那咱就开始造人吧,哦,不对,女娲开始造人了:
public class Test {
    //女娲建立起了两条生产线,分别是男性生产线和女性生产线
    public static void main(String[] args) {
        //第一条生产线,男性生产线,可以生产各种各样的男性
        IHumanFactory maleHumanFactory = new MaleHumanFactory();
        IHuman maleYellowHuman = maleHumanFactory.createYellowHuman();//生产黄色的男性
        IHuman maleWhiteHuman = maleHumanFactory.createWhiteHuman();//生产白色的男性
        maleYellowHuman.sex();
        maleWhiteHuman.sex();
        System.out.println("\n\n");
        //第二条生产线,女性生产线,可以生产各种各样的女性
        IHumanFactory femaleHumanFactory = new FemaleHumanFactory();
        IHuman femaleYellowHuman = femaleHumanFactory.createYellowHuman();//生产黄色的女性
        IHuman femaleWhiteHuman = femaleHumanFactory.createWhiteHuman();//生产白色的女性
        femaleYellowHuman.sex();
        femaleWhiteHuman.sex();
    }

}


附件列表