03.抽象工厂模式

场景

  1. 随着水果的种类增加,对水果的需求量也增加,由于每次都要客户自己来果园采摘,对客户来说及其不友好,这个时候peter就干起了网上水果店的生意。因为邮寄水果需要包装,这个时候,产品就分为了2个系列:一个水果系列,一个包装盒系列。就相当于水果有自己的水果工厂,包装盒有包装盒工厂。
    在这里插入图片描述

  2. 但是网店还没有开多久就收到了客户的投诉,说明明买的是苹果,却给我送来芒果,那谁知道客户还对芒果过敏,这使得peter赔了一笔钱还得到了差评。于是peter就去工厂查找原因,刚好就看到小王在包装芒果的时候,TMD拿了苹果的盒子。害!原来小王是个憨憨,因为不同种类的盒子都放在那个地方,一不小心就拿错了,peter大怒,当即对小王做罚款250元的惩罚。

在这里插入图片描述

  1. 在经过上面的事情之后,peter就想了一个法子,让苹果和苹果包装盒呆在一起,桔子和桔子包装盒呆在一起,这样应该就不会出错了,于是就有了下面的方式。当使用不同工厂时,返回对应这一族的产品系列。

在这里插入图片描述

抽象工厂模式

定义

提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类。即当一个类别的产品还有多个系列区分时,为了按系列生产商品,使用抽象工厂区分。

结构

  • 抽象工厂(Abstract Factory):提供了创建产品的接口,它包含多个创建产品的方法 newProduct(),可以创建多个不同等级的产品。

  • 具体工厂(Concrete Factory):主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建。

  • 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品。

  • 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它 同具体工厂之间是多对一的关系。

UML类图

在这里插入图片描述

代码实现

实现

水果&包装接口(抽象产品)

public interface Fruit {

    public void getFruit();
}

public interface Bag {
    //打包
    void pack();
}

水果&包装种类(具体产品)

/**
 * 苹果
 */
public class Apple implements Fruit {
    @Override
    public void getFruit() {
        System.out.print("我是苹果");
    }
}

/**
 * 香蕉
 */
public class Banana implements Fruit {
    @Override
    public void getFruit() {
        System.out.print("我是香蕉");
    }
}

/**
 * 桔子
 */
public class Orange implements Fruit {
    @Override
    public void getFruit() {
        System.out.print("我是桔子");
    }
}
-----------------------------------------------------------------------------------------
/**
 * 苹果包装
 */
public class AppleBag implements Bag {
    @Override
    public void pack() {
        System.out.print("--我使用苹果盒包装");
    }
}

/**
 * 香蕉包装
 */
public class BananaBag implements Bag {
    @Override
    public void pack() {
        System.out.print("--我使用香蕉盒包装");
    }
}

/**
 * 桔子包装
 */
public class OrangeBag implements Bag {
    @Override
    public void pack() {
        System.out.print("--我使用桔子盒包装");
    }
}

工厂方法(抽象工厂)

/**
 * 抽象工厂接口
 */
public abstract class AbstractFactory {
    /**
     * 获取水果
     */
    public abstract Fruit getFruit();

    /**
     * 包装水果
     */
    public abstract Bag getBag();
}

工厂方法(具体产品)

/**
 * 苹果工厂
 */
public class AppleFactory extends AbstractFactory {
    @Override
    public Fruit getFruit() {
        return new Apple();
    }

    @Override
    public Bag getBag() {
        return new AppleBag();
    }
}

/**
 * 香蕉工厂
 */
public class BananaFactory extends AbstractFactory {
    @Override
    public Fruit getFruit() {
        return new Banana();
    }

    @Override
    public Bag getBag() {
        return new BananaBag();
    }
}

/**
 * 桔子工厂
 */
public class OrangeFactory extends AbstractFactory {
    @Override
    public Fruit getFruit() {
        return new Orange();
    }

    @Override
    public Bag getBag() {
        return new OrangeBag();
    }
}

客户端调用

public class TestClient {

    public static void main(String[] args) {
        //初始化工厂
        //AbstractFactory factory = new BananaFactory();
        AbstractFactory factory = new BananaFactory();
        Fruit apple = factory.getFruit();
        apple.getFruit();
        Bag bag = factory.getBag();
        bag.pack();
    }
}

结果

我是香蕉--我使用香蕉盒包装

优缺点

优点

  • 可以在类的内部对产品族中相关联的多等级产品共同管理,而不必专门引入多个新的类来进行管理。
  • 当增加一个新的产品族时不需要修改原代码,满足开闭原则。

缺点

  • 当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。

抽象工厂模式的本质

抽象工厂模式的本质:选择产品簇(族)实现

使用场景

  • 当需要创建的对象是一系列相互关联或相互依赖的产品族时,如电器工厂中的电视机、洗衣机、空调等。
  • 系统中有多个产品族,但每次只使用其中的某一族产品。如有人只喜欢穿某一个品牌的衣服和鞋。
  • 系统中提供了产品的类库,且所有产品的接口相同,客户端不依赖产品实例的创建细节和内部结构。

模式的扩展

抽象工厂模式的扩展有一定的“开闭原则”倾斜性:

  • 当增加一个新的产品族时只需增加一个新的具体工厂,不需要修改原代码,满足开闭原则。

  • 当产品族中需要增加一个新种类的产品时,则所有的工厂类都需要进行修改,不满足开闭原则。

另一方面,当系统中只存在一个等级结构的产品时,抽象工厂模式将退化到工厂方法模式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

汪了个王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值