Java设计模式之工厂模式详解

简单工厂其实并不是设计模式,只是一种编程习惯。

首先我们创建父类Cup,所有杯子类的父类。再创建它的子类BigCup和SmallCup类。

public abstract class Cup {
    public abstract void use();
}

public class BigCup extends Cup {
    @Override
    public void use() {
        System.out.println("大杯装500ml水");
    }
}

public class SmallCup extends Cup {
    @Override
    public void use() {
        System.out.println("小杯装100ml水");
    }
}

然后我们创建工厂类CupFactory,工厂里声明了Cup引用,根据传入的参数type来判断生产什么类型的杯子,这样外部只需要传入类型就可以生成想要的类型的对象,现在运行看一下结果,没有问题。

public static void main(String[] args){
    CupFactory cupFactory = new CupFactory();
    Cup smallCup = cupFactory.makeCup("small");
    smallCup.use();
    Cup bigCup = cupFactory.makeCup("big");
    bigCup.use();
}

结果:
小杯装100ml水
大杯装500ml水

简单工厂虽然解决了一些问题但是当我们的需要增加子类的时候就很麻烦了,需要修改工厂类里的代码,违反了开放封闭原则,所以我们现在使用真正的工厂模式来解决这个问题。

工厂模式,又称为工厂方法模式。定义了一个创建产品对象的工厂接口,将实际创建工作推迟到子类工厂当中。

首先我们创建抽象类Tableware,代表所有餐具的父类,再创建一个抽象工厂类TablewareFactory,抽象工厂里面有抽象方法makeTableware来制造餐具。然后我们创建4个餐具子类,分别是BigBowl、SmallBowl、BigCuphe和SmallCup。

public abstract class Tableware {
    public abstract void use();
}

public abstract class TableWareFactory {
    public abstract Tableware makeTableware(String type);
}

public class BigBowl extends Tableware {
    @Override
    public void use() {
        System.out.println("大碗装500g饭");
    }
}

public class SmallBowl extends Tableware {
    @Override
    public void use() {
        System.out.println("小碗装100g饭");
    }
}

public class BigCup extends Tableware {
    @Override
    public void use() {
        System.out.println("大杯装500ml水");
    }
}

public class SmallCup extends Tableware {
    @Override
    public void use() {
        System.out.println("小杯装100ml水");
    }
}

接下来我们需要实现工厂类了,这是最关键的部分,从上述4个子类可以看出,BigBowl和SmallBowl是一类产品,而BigCup和SamllCup是另一类,所以我们创建两个子类工厂,分别是BowlFactory和CupFactory。它们生产不同的产品,但是又能根据参数来生产不同规格的同类产品。在子类工厂中的makeTableware方法才是决定生产什么产品,而父类工厂并不知道,这就是将实际创建工作推迟到子类工厂当中。当我们想要新建别的产品的时候增加新的子类工厂即可。

public class BowlFactory extends TableWareFactory {

    @Override
    public Tableware makeTableware(String type) {
        Tableware tableware = null;
        if (type.equals("big")){
            tableware = new BigBowl();
        }else if (type.equals("small")){
            tableware = new SmallBowl();
        }
        return tableware;
    }
}

public class CupFactory extends TableWareFactory {
    @Override
    public Tableware makeTableware(String type) {
        Tableware tableware = null;
        if (type.equals("big")){
            tableware = new BigCup();
        }else if (type.equals("small")){
            tableware = new SmallCup();
        }
        return tableware;
    }
}

测试一下看看结果,结果没有问题。

TableWareFactory cupFactory = new CupFactory();
Tableware bigCup = cupFactory.makeTableware("big");
bigCup.use();
Tableware smallCup = cupFactory.makeTableware("small");
smallCup.use();
TableWareFactory bowlFactory = new BowlFactory();
Tableware bigBowl =  bowlFactory.makeTableware("big");
bigBowl.use();
Tableware smallBowl = bowlFactory.makeTableware("small");
smallBowl.use();

结果:
大杯装500ml水
小杯装100ml水
大碗装500g饭
小碗装100g饭

抽象工厂模式其实是在工厂方法模式的基础上加入了产品族的概念,也就是工厂里会生产多种产品,他们需要配套使用,例如衣服和裤子。

我们先创建一个抽象工厂BaseFactory类,有两个抽象方法makeTableware和getFood,分别生产餐具和食物,因为它们两个是要配合使用的。

public abstract class BaseFactory {
    public abstract Tableware makeTableware();
    public abstract  Food getFood();
}

然后我们创建餐具的抽象父类Tableware和事物的抽象父类Food,再创建它们的子类BigBowl、SmallCup、Meat和Milk类。

public abstract class Tableware {
    public abstract void use();
}

public abstract class Food {
    public abstract void name();
}

public class BigBowl extends Tableware {
    @Override
    public void use() {
        System.out.println("500ml的大碗");
    }
}

public class SmallCup extends Tableware {
    @Override
    public void use() {
        System.out.println("100ml的小杯子");
    }
}

public class Meat extends Food {
    @Override
    public void name() {
        System.out.println("肉");
    }
}

public class Milk extends Food {
    @Override
    public void name() {
        System.out.println("牛奶");
    }
}

接下来我们创建两个子类工厂MeatWithBowlFactory和MilkWithCupFactory
类,这两个类把肉和碗分到一个工厂里,牛奶和杯子分到一个工厂里,表示他们需要配套使用。这里的makeTableware和getFood方法也可以像上面工厂方法模式里一样接受参数生成不同规格的产品,现在是直接返回一个对象。

public class MeatWithBowlFactory extends BaseFactory {
    @Override
    public Tableware makeTableware() {
        return new BigBowl();
    }

    @Override
    public Food getFood() {
        return new Meat();
    }
}

public class MilkWithCupFactory extends BaseFactory{
    @Override
    public Tableware makeTableware() {
        return new SmallCup();
    }

    @Override
    public Food getFood() {
        return new Milk();
    }
}

现在测试一下结果,没有问题,同一个工厂可以生产需要配套的产品。

   BaseFactory baseFactory;
   baseFactory = new MeatWithBowlFactory();
   BigBowl bigBowl = (BigBowl) baseFactory.makeTableware();
   bigBowl.use();
   Meat meat = (Meat)baseFactory.getFood();
   meat.name();

   baseFactory = new MilkWithCupFactory();
   SmallCup smallCup = (SmallCup) baseFactory.makeTableware();
   smallCup.use();
   Milk milk = (Milk)baseFactory.getFood();
   milk.name();

结果:
500ml的大碗

100ml的小杯子
牛奶

总结:

  • 简单工厂模式其实只是把创建对象这个常用的工厂做成工厂类方便调用,但是修改的时候需要修改工厂的代码,只是一种编程习惯,不是设计模式。
  • 工厂模式,也就是工厂方法模式是解决了简单工厂要修改代码的问题,他把对象的创建操作延迟到子类工厂中,这样新增产品就不需要修改代码。
  • 抽象工厂模式就是在工厂方法模式的基础上加入了产品族的概念,如果几个产品需要配套使用,就可以将他们放在同一个工厂里自行选择搭配,比如牛肉放在瓷碗里,猪肉放在铁碗里。
    原文作者:设计模式
    原文地址: https://segmentfault.com/a/1190000014391578
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞