Java设计模式之工厂模式

作者: 饱醉豚我去年买了个表 | 来源:发表于2019-10-25 21:17 被阅读0次

写在前面

当我们需要初始化对象时,通常需要关键字new来初始化一个新对象,很方便,但同时也有缺点,那就是强耦合性,当这个对象有改变时,对象所在类也要跟着改变。根据设计规则,我们要对扩展开放,对改变关闭,怎么屏蔽改变呢,可以通过工厂模式找出变化的地方,把他们从不变的部分分离出去。

举个例子

奶茶店里能生产红茶和奶茶,我们需要哪个就会给我们制作哪个,如下:

public interface IDrink {

    void drink();
}
public class TeaDrink implements IDrink {

    @Override
    public void drink() {
        System.out.println("drink: TeaDrink");
    }
}
public class MilkDrink implements IDrink {
    @Override
    public void drink() {
        System.out.println("drink: MilkDrink");
    }
}

上面定义了IDrink接口及两个实现类TeaDrink、MilkDrink,下面开始使用他们:

private static void drinkSomeThing(String type) {
    IDrink drink = null;
    switch (type) {
        case "tea":
            drink = new TeaDrink();
            break;
        case "milk":
            drink = new MilkDrink();
            break;
        default:
            break;
    }
    drink.drink();
}

很简单 根据传入的type展示不同的结果:

传入tea返回的是  drink: TeaDrink
传入milk返回的是  drink: MilkDrink

假如后面又来了个IceDrink(冰激凌),那么就需要继续在这个方法中添加逻辑,如果逻辑复杂了,这个类就会显得很乱,下面用几种工厂模式来重写这个逻辑。

简单工厂模式

简单工厂模式严格来说并不是一种设计模式,内部有一个工厂类,根据不同的条件来创建不同的对象:

public class DrinkFactory {

    public static IDrink getDrink(String type) {
        switch (type) {
            case "tea":
                return new TeaDrink();
            case "milk":
                return new MilkDrink();
            default:
                break;
        }
        return null;
    }
}

调用上面的工厂类:

//简单工厂模式 
//传入milk 在工厂类中创建MilkDrink类并调用其方法
IDrink drink = DrinkFactory.getDrink("milk");
drink.drink();

输出:

drink: MilkDrink

相比于上面的例子代码,简单工厂模式将创建各种茶的逻辑放到一个工厂类中,即将变化的部分抽离出来单独维护,后面如果有变化,直接修改这个工厂类即可。

工厂模式

工厂模式定义了一个创建对象的接口,由子类决定要实例化的类是哪一个,即把类的实例化推迟到了子类中。

工厂模式不同于简单工厂模式,简单工厂模式只有一个工厂类来创建所有的对象,而工厂模式是根据不同的对象来提供不同的工厂。工厂模式有下面4种角色:

  • 抽象工厂:定义所有具体工厂类行为
  • 具体工厂:可以有多个,每个工厂负责生产对应的产品类
  • 抽象产品:定义所有产品类的特性
  • 具体产品:不同具体工厂生产出不同产品

抽象工厂:

public interface IFactory {

    IDrink produce();
}

具体工厂:

public class IceFactory implements IFactory {

    @Override
    public IDrink produce() {

        return new IceCreamDrink();
    }
}
public class TeaFactory implements IFactory {
    @Override
    public IDrink produce() {

        return new TeaDrink();
    }
}

抽象产品:

public interface IDrink {

    void drink();
}

具体产品:

public class IceCreamDrink implements IDrink {

    @Override
    public void drink() {
        System.out.println("drink: IceCream");
    }
}
public class TeaDrink implements IDrink {

    @Override
    public void drink() {
        System.out.println("drink: TeaDrink");
    }
}

调用工厂类:

System.out.println("--------------工厂模式--------------");
//工厂模式
IFactory factory = new IceFactory();
//IFactory factory = new TeaFactory();
IDrink drink1 = factory.produce();
drink1.drink();

结果:

--------------工厂模式--------------
drink: IceCream

工厂模式中,通过子类来创建对应的产品类,作为消费者不需要知道产品是怎么加工的,只需要知道工厂名(奶茶店还是冰激凌店)就可以了。

抽象工厂模式

抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

如果我们的需求又变了:在买奶茶时,可以选择大杯的和小杯的,另外奶茶还可以选择加水果或果仁且是必选。分析上面的需求,我们可以看到大小杯、加水果或果仁都是生产奶茶的其中一个步骤,结合抽象工厂的定义,我们可以使用抽象工厂模式来实现我们的需求。

抽象原料:

public interface IRaw {
    //用来定义加果仁还是水果
    void produceRaw();
}

public interface IShape {
    //用来定义大小杯
    void produceShape();
}

具体原料:


public class BigShape implements IShape {
    @Override
    public void produceShape() {
        System.out.println("Shape:大杯");
    }
}

public class SmallShape implements IShape {
    @Override
    public void produceShape() {
        System.out.println("Shape:小杯");
    }
}

public class FruitRaw implements IRaw {

    @Override
    public void produceRaw() {
        System.out.println("produceRaw:添加水果");
    }
}

public class NutRaw implements IRaw {

    @Override
    public void produceRaw() {
        System.out.println("produceRaw:添加果仁");
    }
}

抽象工厂:

public interface IBaseFactory {

    IShape buildShape();

    IRaw buildRaw();

}

具体工厂:

//生产大杯加果仁的奶茶
public class AFactory implements IBaseFactory {

    @Override
    public IShape buildShape() {
        return new BigShape();
    }

    @Override
    public IRaw buildRaw() {

        return new NutRaw();
    }
}

//生产小杯加水果的
public class BFactory implements IBaseFactory {

    @Override
    public IShape buildShape() {

        return new SmallShape();
    }

    @Override
    public IRaw buildRaw() {

        return new FruitRaw();
    }
}

调用上面的抽象工厂生产奶茶:

System.out.println("--------------抽象工厂模式--------------");
//抽象工厂模式
IRaw raw;
IShape shape;
IBaseFactory baseFactory;
//大杯加果仁的
baseFactory = new AFactory();
//小杯加水果的
// baseFactory = new BFactory();

raw = baseFactory.buildRaw();
shape = baseFactory.buildShape();
shape.produceShape();
raw.produceRaw();

结果:

--------------抽象工厂模式--------------
Shape:大杯
produceRaw:添加果仁

抽象工厂模式和工厂模式看似是一样的,他们确实相似度很高,但是还是有区别的,工厂模式中的工厂类只能创建一个具体对象,而在抽象工厂模式中,工厂类可以创建一组对象(例子中创建了大杯类、果仁类),这是他们之间的不同点。

相关文章

  • 工厂模式

    java设计模式-工厂模式 工厂模式: 工厂模式是java设计模式里最常用的设计模式之一。 工厂模式属于创建型模式...

  • Java与模式

    《JAVA与模式》之简单工厂模式《JAVA与模式》之工厂方法模式《JAVA与模式》之抽象工厂模式

  • Java设计模式教程

    Java设计模式教程 Java工厂设计模式 Java抽象工厂模式 Java单例模式 Java建造者(Builder...

  • 代码段简单学习设计模式 -- 抽象工厂模式

    《JAVA与模式》之抽象工厂模式 大话设计模式 抽象工厂模式(Abstraci Factory): 提供一个创...

  • iOS设计模式(三)之抽象工厂模式

    设计模式系列传送门 iOS设计模式(一)之简单工厂模式iOS设计模式(二)之工厂模式iOS设计模式(三)之抽象工厂...

  • iOS设计模式(一)之简单工厂模式

    设计模式系列传送门 iOS设计模式(一)之简单工厂模式iOS设计模式(二)之工厂模式iOS设计模式(三)之抽象工厂...

  • iOS设计模式(二)之工厂模式

    设计模式系列传送门 iOS设计模式(一)之简单工厂模式iOS设计模式(二)之工厂模式iOS设计模式(三)之抽象工厂...

  • java设计模式

    一、《JAVA与模式》之工厂方法模式 二、《JAVA与模式》之抽象工厂模式 三、《JAVA与模式》之单例模式 四、...

  • 工厂模式(Factory Pattern)

    大话设计模式之陈狗养猪记_工厂模式 概念: 工厂模式(Factory Pattern)是 Java 中最常用的...

  • 设计模式 - 工厂模式

    概述 我们都知道Java中共有 23 种设计模式,其中工厂模式分为三种,即:简单工厂模式(不在 23 种设计模式之...

网友评论

    本文标题:Java设计模式之工厂模式

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