美文网首页
23种设计模式-抽象工厂模式

23种设计模式-抽象工厂模式

作者: stayiwithime | 来源:发表于2019-05-15 20:04 被阅读0次
  1. 女娲的失误

工厂方法模式举了女娲造人的例子,人是造出来了,世界也热闹了,可以低头一看,都是清一色的类型,没有给人类定义性别。在现有条件下重新造人,尽可能旧物利用。人种(Product产品类)应该怎么改造呢?就增加了性别的区分,那么目前的对象通过肤色和性别可以确定了,产品分析完毕了,生产的工厂类(八卦炉)该怎么改造呢?把现有的八卦炉拆开,分别去生产女性和男性,类图9-2:


9-2

类图虽然很大,但是比较简单。java的典型类图,一个接口,多个抽象类,然后是N个实现类,每个人种是一个抽象类,性别在各个实现类中是想。需要说明的是HumanFactory接口,在这个接口中定义了三个方法,分别用来生产三个不同肤色的人种,它的两个实现类分别是性别,通过肤色和性别唯一确定一个生产出来的对象。
代码如下:

//人类接口
public interface Human {
    void getColor();
    void getSex();
}
//人种抽象类
public abstract class AbstractBlackHuman implements Human {
    @Override
    public void getColor() {
        System.out.println("黑人");
    }
}
public abstract class AbstractWhiteHuman implements Human {
    @Override
    public void getColor() {
        System.out.println("白人");
    }
}
public abstract class AbstractYellowHuman implements Human {
    @Override
    public void getColor() {
        System.out.println("黄种人");
    }
}
//区分性别的具体实现
public class FemaleBlackHuman extends AbstractBlackHuman {
    @Override
    public void getSex() {
        System.out.println("黑人女性");
    }
}
public class MaleBlackHuman extends AbstractBlackHuman {
    @Override
    public void getSex() {
       System.out.println("黑人男性");
    }
}
public class FemaleWhiteHuman extends AbstractWhiteHuman{
    @Override
    public void getSex() {
        System.out.println("白人女性");
    }
}
public class MaleWhiteHuman extends AbstractWhiteHuman {
    @Override
    public void getSex() {
        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 {
    Human createYellowHuman();
    Human createBlackHuman();
    Human createWhiteHuman();
}
//工厂实现
public class FemaleFactory implements HumanFactory {
    @Override
    public Human createYellowHuman() {
        return new FemaleYellowHuman();
    }

    @Override
    public Human createBlackHuman() {
        return new FemaleBlackHuman();
    }

    @Override
    public Human createWhiteHuman() {
        return new FemaleWhiteHuman();
    }
}
public class MaleFactory implements HumanFactory {
    @Override
    public Human createYellowHuman() {
        return new MaleYellowHuman();
    }

    @Override
    public Human createBlackHuman() {
        return new MaleBlackHuman();
    }

    @Override
    public Human createWhiteHuman() {
        return new MaleWhiteHuman();
    }
}

回过头来想想我们的设计,有点像工厂,每个工厂分很多车间,每个车间又分多条生产线,分别生产不同的产品,我们可以把八卦炉看做车间,把八卦炉生产的工艺(生产白人、黑人还是黄人)称为生产线,如此来看就是一个女性生产车间,专门生产各种肤色的女性,一个是男性生产车间,专门生产各种肤色的男性。在这样的设计下,各个车间和各条生产线的职责非常明确,在车间内各个生产出来的产品可以有耦合关系,还可以在车间内协调好生产比例,这就是抽象工厂模式。

  1. 抽象工厂模式的定义

抽象工厂模式(abstract factory pattern)是一种比较常用的模式,其定义如下:
Provide an interface for creating families of related or dependent objects without specifying their concreate classes(为创建一组相关或相互依赖的对象提供一个接口,而且无须指定他们的具体类。)
抽象工厂模式的通用类图9-3:

9-3
抽象工厂模式是工厂方法模式的升级版本,在有多个业务品种、业务分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式。我们来看看抽象工厂的通用源代码,首先有两个互相影响的产品线(也叫做产品族),例如制造汽车的左侧车门和右侧门,这两个应该是数量相等的——两个对象之间的约束,每个型号的车门都是不一样的,这是产品等级结构约束的,我们先看看两个产品族的类图,类图9-4:
9-4
注意类图上的圈圈、框框相对应,两个抽象的产品类可以有关系,例如共同继承或实现一个抽象或接口,代码如下:
//A类产品抽象类
public abstract class AbstractProductA {
    //每个产品共有方法
    public void shareMethod(){
        System.out.println("这是A类产品");
    }
    //每个产品相同方法,不同实现
    public abstract void doSomething();
}
//A类产品的两个实现类
public class ProductA1 extends AbstractProductA {
    @Override
    public void doSomething() {
        System.out.println("ProductA1的实现");
    }
}
public class ProductA2 extends AbstractProductA {
    @Override
    public void doSomething() {
        System.out.println("ProductA2的实现");
    }
}
//B类产品
public abstract class AbstractProductB {
    public void shareMethod(){
        System.out.println("这是B类产品");
    }
    public abstract void doSomething();
}
public class ProductB1 extends AbstractProductB {
    @Override
    public void doSomething() {
        System.out.println("ProductB1的实现");
    }
}
public class ProductB2 extends AbstractProductB {
    @Override
    public void doSomething() {
        System.out.println("ProductB2的实现");
    }
}
//抽象工厂接口
public interface AbstractFactory {
    AbstractProductA createProductA();
    AbstractProductB createProductB();
}
//工厂实现类
public class Product1Factory implements AbstractFactory {
    @Override
    public AbstractProductA createProductA() {
        return new ProductA1();
    }

    @Override
    public AbstractProductB createProductB() {
        return new ProductB1();
    }
}
public class Product2Factory implements AbstractFactory {
    @Override
    public AbstractProductA createProductA() {
        return new ProductA2();
    }

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

抽象工厂类AbstractFactory 的职责是定义每个工厂要实现的功能,在通用代码中,抽象工厂定义了两个产品族的产品创建,有N个产品族,在抽象工厂类中就应该有N个创建方法(那这样不是就不太方便扩展,增加一个产品族就需要增加一个创建方法,还是说通过接口在实现抽象工厂接口去增加方法,感觉这样也不太合理,这些产品族一般应该会有一定得依赖关系会有耦合的,如果通过继承接口去扩展好像也会有问题,这个具体看后面是怎么处理的
这里有M个产品等级就应该有M个实现工厂,在每个实现工厂中,实现不同产品族的生产任务。该模式中,对于一个产品来说,我们只要知道它的工厂方法就可以直接产生一个产品对象,无须关系他的实现类。(就是将产品的生产全交给工厂负责,我们只需要在使用的时候去生产就好了

  1. 抽象工厂模式的应用

3.1抽象工厂模式的优点

  • 封装性,每个产品的实现类不是高层模块关心的,他要关心的是什么?是接口,是抽象,他不关心对象是如何创建出来的,这都由工厂类负责,只要知道工厂类是谁,就可以创建出需要的对象 ,这不就很符合依赖倒置原则,抽象完成依赖。
  • 产品族内的约束为非公开状态。比如生产产品的比例可以在工厂内实现,像左车门和右车门的比例是1比1,这样的生成过程对调用工厂类的高层模块来说是透明的,他不需要知道这个约束。(这个的具体应用我自己还没见到过实例,也想不到会用在哪个地方,怎么用
    3.2抽象工厂模式的缺点
    抽象工厂模式的最大缺点就是产品族扩展非常困难(这个就是我上面有提到的问题,没想到没给出解决方案,实在的缺陷)为什么这么说?我们通过代码为例,如果要增加一个产品c,也就是产品家族由原来的2个增加到3个,抽象类AbstractFactory要增加一个方法createProductC(),然后两个实现类都要修改,这严重违反了开闭原则,而且我们一直说明抽象类和接口是一个契约。改变契约,所有与契约有关的代码都需要修改,这叫“有毒代码”,只要与这段代码有关,就可能产生侵害的危险。
    3.3抽象工厂模式的使用场景
    抽象工厂模式的使用场景定义非常简单:一个对象族(或一组没有任何关系的对象)都有相同的约束,则可以使用抽象工厂模式。什么意思呢?例如一个文本编辑器和一个图片处理器,都是软件实体,但是linux下的文本编辑器和windows下的文本编辑器虽然功能和界面都相同,但是代码实现是不同的,图片编辑器也有类似情况。也就是具有共同的约束条件:操作系统类型。于是我们可以使用抽象工厂模式,产生不同操作系统下的编辑器和图片处理器。
    3.4抽象工厂模式的注意事项
    缺点是产品族扩展比较困难,但是一定要搞清楚,难得是产品族,不是产品等级(product1,product2)。该模式下,产品等级是非常容易扩展的,增加一个产品等级,只要增加一个工厂类负责新增出来的产品生成任务即可。也就是说横向扩展容易,纵向扩展难,从产品等级扩展看是符合开闭原则的,这个可以看上面的通用类图代码的例子。
  1. 最佳实践

一个模式在什么情况下才能够使用,这是我们都比较关注的点。抽象工厂模式是一个简单的模式,使用的场景非常多,例如在开发中,涉及到不同操作系统的时候,都可以考虑使用抽象工厂模式,通过抽象工厂模式屏蔽掉操作系统对应用的影响。(这个说起来很容易,但是具体怎样去理解,怎样去使用,还是需要多实践,只有见过做过才会印象更深

内容来自《设计模式之禅》

相关文章

  • 设计模式四、抽象工厂模式

    系列传送门设计模式一、单例模式设计模式二、简单工厂模式设计模式三、工厂模式设计模式四、抽象工厂模式 抽象工厂模式 ...

  • 常用设计模式

    设计模式 工厂模式 工厂模式思路上分:简单工厂模式,工厂模式, 抽象工厂模式// 抽象工厂模式可以代替工厂模式,做...

  • 单件设计模式

    一、定义 设计模式 设计模式就是一种更好的编写代码方案。 常见设计模式 工厂设计模式、抽象工厂设计模式、抽象工厂设...

  • Android 源码设计模式解析与实战 读书笔记 6 抽象工厂模

    创建型设计模式 —— 抽象工厂模式 1. 抽象工厂模式介绍 抽象工厂模式(Abstract Factory Pat...

  • 设计模式系列-抽象工厂模式

    JAVA设计模式系列: 单例模式 观察者模式 模板方法模式 简单工厂模式 抽象工厂模式 抽象工厂模式 定义 抽象工...

  • Go语言设计模式(3)抽象工厂模式

    Go语言设计模式(3)抽象工厂模式 抽象工厂模式的定义 抽象工厂模式的定义如下: Provide an inter...

  • 2021-11-16 - 学习记录

    设计模式学习:创建型:工厂(工厂方法,抽象工厂),建造者,单例,原型 设计模式:工厂模式 简单工厂 工厂方法 抽象工厂

  • 创建型设计模式

    一 . 工厂模式 二. 抽象工厂设计模式

  • 设计模式三、工厂模式

    系列传送门设计模式一、单例模式设计模式二、简单工厂模式设计模式三、工厂模式设计模式四、抽象工厂模式 工厂模式 在一...

  • 抽象工厂模式

    抽象工厂设计模式 介绍 抽象工厂设计模式是设计模式中“创建型模式”中的一种,它是用来创建其它工厂的超级工厂。所以该...

网友评论

      本文标题:23种设计模式-抽象工厂模式

      本文链接:https://www.haomeiwen.com/subject/izfyaqtx.html