您当前的位置: 首页 > 

Dongguo丶

暂无认证

  • 2浏览

    0关注

    472博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

设计模式之抽象工厂模式

Dongguo丶 发布时间:2019-01-10 19:01:25 ,浏览量:2

在工厂方法模式中,我们使用一个工厂创建一个产品,也就是说一个具体的工厂对应一个具体的产品。但是有时候我们需要一个工厂能够提供多个产品对象,而不是单一的对象,这个时候我们就需要使用抽象工厂模式。

抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的,抽象工厂迷失可以向客户端提供一个接口,使得客户端在不必指定产品的具体类型的情况下,能够创建多个产品族的产品对象。

在讲解抽象工厂模式之前,我们需要厘清两个概念:

产品等级结构。产品的等级结构也就是产品的继承结构。例如一个为空调的抽象类,它有海尔空调、格力空调、美的空调等一系列的子类,那么这个抽象类空调和他的子类就构成了一个产品等级结构。

产品族。产品族是在抽象工厂模式中的。在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品。比如,海尔工厂生产海尔空调。海尔冰箱,那么海尔空调则位于空调产品族中。

产品等级结构和产品族结构示意图如下:

UML结构图

模式结构说明:

AbstractFactory:抽象工厂。抽象工厂定义了一个接口,所有的具体工厂都必须实现此接口,这个接口包含了一组方法用来生产产品。

ConcreteFactory:具体工厂。具体工厂是用于生产不同产品族。要创建一个产品,客户只需要使用其中一个工厂完全不需要实例化任何产品对象。

AbstractProduct:抽象产品。这是一个产品家族,每一个具体工厂都能够生产一整组产品。

Product:具体产品。

还是用之前的水果的例子

现在有两个产品族: 南方水果, 北方水果

产品结构 :苹果、香蕉

package com.dongguo.absfactory.fruit1;

/**
 * @author Dongguo
 * @date 2021/8/22 0022-10:15
 * @description:
 */
public interface Fruit {
    public void eat();
}

package com.dongguo.absfactory.fruit1;

/**
 * @author Dongguo
 * @date 2021/8/22 0022-10:23
 * @description:
 */
public abstract class Apple implements Fruit{
    public abstract void eat();
}

package com.dongguo.absfactory.fruit1;

/**
 * @author Dongguo
 * @date 2021/8/22 0022-10:16
 * @description:
 */
public abstract class Banana implements Fruit{
    public abstract void eat();
}

package com.dongguo.absfactory.fruit1;

/**
 * @author Dongguo
 * @date 2021/8/22 0022-11:08
 * @description:
 */
public class NorthApple extends Apple {
    @Override
    public void eat() {
        System.out.println("吃南方的苹果");
    }
}

package com.dongguo.absfactory.fruit1;
/**
 * @author Dongguo
 * @date 2021/8/22 0022-11:08
 * @description:
 */
public class SouthApple extends Apple{
    @Override
    public void eat() {
        System.out.println("吃北方的苹果");
    }
}

package com.dongguo.absfactory.fruit1;
/**
 * @author Dongguo 
 * @date 2021/8/22 0022 11:10 
 * @description:
 */
public class NorthBanana extends Banana {
    @Override
    public void eat() {
        System.out.println("吃南方的香蕉");
    }
}

package com.dongguo.absfactory.fruit1;
/**
 * @author Dongguo 
 * @date 2021/8/22 0022 11:10 
 * @description:
 */
public class SouthBanana extends Banana {
    @Override
    public void eat() {
        System.out.println("吃北方的香蕉");
    }
}

水果分为苹果和香蕉  苹果分为南方苹果、北方苹果 香蕉分为南方香蕉、北方香蕉

那我们使用抽象工厂模式是如何实现的呢:

 创建FruitFactory 有两个方法分别是获取Apple实例和Banana实例

package com.dongguo.absfactory.fruit1;

/**
 * @author Dongguo
 * @date 2021/8/22 0022-11:12
 * @description:
 */
public interface FruitFactory {
    //实例化Apple
    public Fruit getApple();
    //实例化Banana
    public Fruit getBanna();
}

 南方水果工厂获得南方苹果和南方香蕉的实例

package com.dongguo.absfactory.fruit1;

/**
 * @author Dongguo
 * @date 2021/8/22 0022-11:14
 * @description:
 */
public class NorthFruitFactory implements FruitFactory {

    public Fruit getApple() {
        return new NorthApple();
    }

    public Fruit getBanna() {
        return new NorthBanana();
    }
}

  北方水果工厂获得北方苹果和北方香蕉的实例

package com.dongguo.absfactory.fruit1;

/**
 * @author Dongguo
 * @date 2021/8/22 0022-11:15
 * @description:
 */
public class SouthFruitFactory implements FruitFactory {
    public Fruit getApple() {
        return new SouthApple();
    }

    public Fruit getBanna() {
        return new SouthBanana();
    }
}
package com.dongguo.absfactory.fruit1;

/**
 * @author Dongguo
 * @date 2021/8/22 0022-11:15
 * @description:
 */
public class AbsFactory {
    public static void main(String[] args) {
        FruitFactory ff = new NorthFruitFactory();
        Fruit northApple = ff.getApple();
        northApple.eat();
        Fruit northBanna = ff.getBanna();
        northBanna.eat();

        FruitFactory ff1 = new SouthFruitFactory();
        Fruit southApple = ff1.getApple();
        southApple.eat();
        Fruit southBanana = ff1.getBanna();
        southBanana.eat();
    }
}
运行结果:
吃南方的苹果
吃南方的香蕉
吃北方的苹果
吃北方的香蕉

此时又新加了一个产品族 温室水果

package com.dongguo.absfactory.fruit1;

/**
 * @author Dongguo
 * @date 2021/8/22 0022-11:16
 * @description:
 */
public class GreenhouseApple extends Apple{
    @Override
    public void eat() {
        System.out.println("吃温室苹果");
    }
}
package com.dongguo.absfactory.fruit1;

/**
 * @author Dongguo
 * @date 2021/8/22 0022-11:17
 * @description:
 */
public class GreenhouseBanana extends Banana{
    @Override
    public void eat() {
        System.out.println("吃温室香蕉");
    }
}
package com.dongguo.absfactory.fruit1;

/**
 * @author Dongguo
 * @date 2021/8/22 0022-11:17
 * @description:
 */
public class GreenhouseFruitFactory implements FruitFactory {
    @Override
    public Fruit getApple() {
        return new GreenhouseApple();
    }

    @Override
    public Fruit getBanna() {
        return new GreenhouseBanana();
    }
}
package com.dongguo.absfactory.fruit1;

/**
 * @author Dongguo
 * @date 2021/8/22 0022-11:15
 * @description:
 */
public class AbsFactory {
    public static void main(String[] args) {
        FruitFactory ff = new NorthFruitFactory();
        Fruit northApple = ff.getApple();
        northApple.eat();
        Fruit northBanna = ff.getBanna();
        northBanna.eat();

        FruitFactory ff1 = new SouthFruitFactory();
        Fruit southApple = ff1.getApple();
        southApple.eat();
        Fruit southBanana = ff1.getBanna();
        southBanana.eat();
        FruitFactory ff2 = new GreenhouseFruitFactory();
        Fruit greenhouseApple = ff2.getApple();
        greenhouseApple.eat();
        Fruit greenhouseBanna = ff2.getBanna();
        greenhouseBanna.eat();
    }
}
运行结果:
吃南方的苹果
吃南方的香蕉
吃北方的苹果
吃北方的香蕉
吃温室苹果
吃温室香蕉

优点

1、 抽象工厂隔离了具体类的生成,是的客户端不需要知道什么被创建。所有的具体工厂都实现了抽象工厂中定义的公共接口,因此只需要改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。

2、 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。

缺点

添加新的行为时比较麻烦。如果需要添加一个新产品族对象时,需要更改接口及其下所有子类,这必然会带来很大的麻烦。

模式使用场景

一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有类型的工厂模式都是重要的。

系统中有多于一个的产品族,而每次只使用其中某一产品族。

  1. 属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。
  2. 系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。
总结

抽象工厂模式中主要的优点在于具体类的隔离,是的客户端不需要知道什么被创建了。其缺点在于增加新的等级产品结构比较复杂,需要修改接口及其所有子类。

抽象工厂中方法对应产品结构,具体工厂对应产品族

关注
打赏
1638062488
查看更多评论
立即登录/注册

微信扫码登录

0.0369s