简单工厂 & 工厂方法 & 抽象工厂 模式

1. 简单工厂模式

1.1 定义

将apple、orange对象的new操作全部集成到1个工厂(SimpleFactory)中,并通过创建的方法(如buy)传入的水果名(name)创建指定的水果的方法,称为简单工厂模式。它的名字是由于这个工厂设计简单。

简单工厂示意图

1.2 代码实现

水果类的代码

public interface Fruit {
    void eat();
}

public class Apple implements Fruit {
    @Override
    public void eat(){
        System.out.println("吃大苹果!");
    }
}

public class Orange implements Fruit {
    @Override
    public void eat(){
        System.out.println("吃大橙子!");
    }
}

简单工厂的代码(重要部分

public class SimpleFactory {
	/**
     * 简单工厂模式按照客户给定的fruitName,提供相应的水果。
     * 优点:实现简单。
     * 缺点:
     *   1.工厂想生产新的水果时,需要增加对应的`水果类`和修改`SimpleFactory`
     *   2.客户不知道有哪些水果可以选购,需要看简单工厂的购买函数、api
     */
    public Fruit buy(String fruitName){
        switch (fruitName){
            case "apple":
                return new Apple();
            case "orange":
                return new Orange();
        }
        return null;
    }
}

2. 工厂方法模式

2.1 定义

定义1个用于创建对象的接口,让子类(或客户端)决定实例化哪一个类。在简单工厂模式中,若客户的需求扩展了,已有的简单工厂(SimpleFactory类)也要跟着变动,这破坏了开闭原则,而工厂方法模式在解决这个问题时,只需要增加新的工厂类,随后客户端切换新的工厂实例即可。

![在这里插入图片描述](https://img-blog.csdnimg.cn/20210405154341537.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTA1MTY5NTI=,size_16,color_FFFFFF,t_70#pic_center

2.2 代码实现

水果类的代码(与1.2节相同)

public interface Fruit {
    void eat();
}

public class Apple implements Fruit {
    @Override
    public void eat(){
        System.out.println("吃大苹果!");
    }
}

public class Orange implements Fruit {
    @Override
    public void eat(){
        System.out.println("吃大橙子!");
    }
}

工厂的代码

public interface FactoryMethod {
    Fruit buy();
}

public class AppleFactory implements FactoryMethod {
    public Fruit buy(){
        return new BigApple();
    }
}

public class OrangeFactory implements FactoryMethod {
    public Fruit buy(){
        return new BigOrange();
    }
}

客户端的代码

public class Client1 {
    public static void main(String[] args) {
        /**
         * 工厂方法模式:
         *   为了解决简单工厂在增加产品时,需要更改工厂类,这违背了开闭原则,于是将选择产品的逻辑抽出来由客户端决定。
         * 场景:
         *   客户1需要大苹果,在寻找工厂时,指定大苹果的工厂即可。
         * 优点:
         *   工厂方法将选择生产品类型的逻辑,放到了客户端。因此在增加产品时,只需要增加工厂类即可;而客户端可以结合自己需要去选择。
         * 缺点:
         *   用户需要记住所有要用的具体工厂类名。倘若客户1经常吃大苹果、小橙子,那每次去购物时,要去这2个工厂购买,会花销许多的时间在路上;
         *   那么如果客户需要记住100个工厂名呢?是不是都要崩溃了?为了解决这个问题,引入抽象工厂,请看下一个部分。
         */
        FactoryMethod factory = new BigAppleFactory();
        Fruit apple = factory.buy();
        apple.eat();
    }
}

3. 抽象工厂模式

当你在熟悉了工厂方法模式后,你会发现它的设计似乎到了极致,用户可以根据自己的需求选择恰当的工厂。但是你是否遇到过这样的问题,用MySQL数据库开发数据访问层开发完毕,突然boss说Oracle数据库更快、更高效,刚好boss之前干过一点开发工作,补充到应该只要换个数据源就行了,很容易,让你尽快。(你心里就开始咒骂,数据源切了,SQL格式不一样,全都得改嘛,又有30个表,代码到处都要改!!!我想辞职,老板,你可别再瞎BB了!!!)

问题还是得解决,在这个常见中,程序要么用MySQL数据库,要么就用Oracle数据库,那我把数据源的所有操作都组成1个套餐,上层在用的时候,只需要从套餐中取操作的session不就好了。这就是抽象工厂模式,定义如下:

3.1 定义

定义:提供了一个创建一系列相关相互依赖对象的接口,而无需指定它们具体的类。(工厂方法模式将选择生产的逻辑交给了客户端;抽象工厂模式考虑到客户端记不清特别多的工厂名,又将部分实例打包成1个有特色的工厂,提供给客户)

举个例子:去学校食堂吃饭,小胡喜欢买2个包子和1碗面条,可销售这2类商品的是2个窗口(比作2个工厂,包子厂和面条厂),那小胡想一起吃这2个食物时,必须得记住这2个窗口才能买到想要的食物,这就好比工厂方法模式。倘若某天这2个窗口合并了(也就只有1个工厂了),那小胡只要记住这1个工厂就可以买到所有的食物,是不是会省了很多旅途的走动;又假如某天,某天小胡的食堂又多了1个窗口(卖包子和面条),那是不是他也可以完全只依赖新的工厂呢?

注:每种模式都有各自的优势,有其最适应的场景,在具体应用中,应该结合它们的优点,达到较好的状态,这将有利于源码的管理、迭代等。

3.2 代码实现

水果类的代码

public interface Fruit {
    void eat();
}

public class BigApple implements Fruit {
    @Override
    public void eat(){
        System.out.println("吃大苹果!");
    }
}
public class SmallApple implements Fruit {
    @Override
    public void eat(){
        System.out.println("吃小苹果!");
    }
}

public class BigOrange implements Fruit {
    @Override
    public void eat(){
        System.out.println("吃大橙子!");
    }
}
public class SmallOrange implements Fruit {
    @Override
    public void eat(){
        System.out.println("吃小橙子!");
    }
}

工厂类的代码

/**
* 每个抽象的工厂应该生产客户所需的所有产品
*/
public interface AbstractFactory {
    Fruit buyApple();
    Fruit buyOrange();
}

// 工厂1只生产大苹果、小橙子,它将非常适合某一群客户
public class Factory1 implements AbstractFactory {
    @Override
    public Fruit buyApple() {
        return new BigApple();
    }

    @Override
    public Fruit buyOrange() {
        return new SmallOrange();
    }
}

// 工厂2只生产小苹果、大橙子,它将非常适合某一群客户
public class Factory2 implements AbstractFactory {
    @Override
    public Fruit buyApple() {
        return new SmallApple();
    }

    @Override
    public Fruit buyOrange() {
        return new BigApple();
    }
}

客户类

public class Client {
    public static void main(String[] args) {
        /**
         * 抽象工厂模式: 由于工厂方法将生产产品的逻辑交给客户端,而客户端因为所需管理的工厂过多,容易产生混乱,于是可以将苹果、橙子开发成套餐的形式,
         *   客户只选择1个套餐(工厂),即可满足所有需求,如此以来可以给客户端提高效率。
         * 优点:
         *   1. 客户自主选择生产厂商的某个套餐,所有产品只依赖该套餐
         * 缺点:
         *   客户端在需要新的套餐时,需要重新定制1个工厂,需要增加的代码比较多。
         */
        AbstractFactory factory = new Factory1();
        Fruit apple = factory.buyApple();
        Fruit orange = factory.buyOrange();
        apple.eat();
        orange.eat();
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

MEMORYLORRY

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

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

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

打赏作者

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

抵扣说明:

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

余额充值