设计模式——工厂模式

工厂模式有简单工厂模式,工厂方法模式,抽象工厂模式三类。

          开始介绍工厂模式之前,先分析一个小案例:一个简单的披萨项目,要便于披萨种类的扩展,便于维护。要求如下:

(1)披萨种类很多,有GreekPizza,CheesePizza等等。

(2)披萨的制作过程为prepare,bake,cut,box。

(3)完成披萨的订购功能。

对上述要求,用传统方式实现如下:
 

// 准备一个抽象得Pizza类,提供四个制作步骤
public abstract class Pizza {
    protected String name;

    public abstract void prepare();
    public void bake() {
        System.out.println(name + " baking");
    }
    public void cut() {
        System.out.println(name + " cutting");
    }
    public void box() {
        System.out.println(name + " boxing");
    }
    public void setName(String name) {
        this.name = name;
    }
}


// 不同种类的Pizza分别继承上述抽象类,重写prepare方法(不同种类的披萨所需材料不同)
public class CheesePizza extends Pizza {
    @Override
    public void prepare() {
        System.out.println("prepare CheesePizza");
    }
}

public class GreekPizza extends Pizza {
    @Override
    public void prepare() {
        System.out.println("prepare GreekPizza");
    }
}
// 订购披萨
public class OrderPizza {
    public OrderPizza() {
        Pizza pizza = null;
        String pizzaType;
        do {
            pizzaType = getType();
            if ("Greek".equals(pizzaType)) {
                pizza = new GreekPizza();
                pizza.setName("GreekPizza");
            } else if ("Cheese".equals(pizzaType)) {
                pizza = new CheesePizza();
                pizza.setName("CheesePizza");
            } else {
                break;
            }
            pizza.prepare();
            pizza.bake();
            pizza.cut();
            pizza.box();
        } while(true);
    }

    // 获取需要订购的披萨种类
    private String getType() {
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("input pizza type:");
            return reader.readLine();
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
    }
}

// 主函数
public static void main(String[] args) {
   new OrderPizza();
}

对上述方法做如下分析:

(1)容易理解,简单易操作。

(2)违反了开闭原则,即对扩展开放,对修改关闭。在这种实现方式中,如果增加一个新的披萨种类,首先要增加一个类去继承Pizza类,还需要在OrderPizza类中增加判断功能,而且,如果有多个OrderPizza类(可以有很多地方订购),则需要修改更多的地方。综上,要新增一个披萨种类,不仅需要修改客户端,还需修改服务端。

(3)针对上述问题可以做以下修改:将创建Pizza对象的操作封装为一个类,如果增加新的披萨种类,只需修改该类即可,这便是简单工厂模式。

简单工厂模式

基本介绍

(1)简单工厂模式是属于创建型模式,是工厂模式的一种,简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。

(2)简单工厂模式为定义一个创建对象的类,由这个类来封装实例化对象的行为。

(3)软件开发中,当我们会用到大量的创建某种,某类或者某批对象时,就会用到工厂模式。(JDK中,Calendar类为使用了简单工厂模式的典型实例)。

实例分析

针对上述实例,我们分析了存在的问题以及修改方式,具体的修改实现如下:

// 将实例化对象的操作封装为一个类
public class SimpleFactory {
    public Pizza createPizza(String pizzaType) {
        Pizza pizza = null;
        if ("Greek".equals(pizzaType)) {
            pizza = new GreekPizza();
            pizza.setName("GreekPizza");
        } else if ("Cheese".equals(pizzaType)) {
            pizza = new CheesePizza();
            pizza.setName("CheesePizza");
        }
        return pizza;
    }
}

// 订购披萨
public class OrderPizza {
    Pizza pizza = null;

    public OrderPizza(SimpleFactory simpleFactory) {
        setSimpleFactory(simpleFactory);
    }

    public void setSimpleFactory (SimpleFactory simpleFactory) {
        String pizzaType = "";
        do {
            pizzaType = getType();
            pizza = simpleFactory.createPizza(pizzaType);
            if (pizza != null) {
                pizza.prepare();
                pizza.bake();
                pizza.cut();
                pizza.box();
            } else {
                break;
            }
        } while(true);
    }
}

// 主方法
public static void main(String[] args) {
    new OrderPizza(new SimpleFactory());
}

为了减少代码量,可以将实例化对象的操作封装为一个静态方法,具体修改如下:

 

public class SimpleFactory {
    public static Pizza createPizza(String pizzaType) {
        Pizza pizza = null;
        if ("Greek".equals(pizzaType)) {
            pizza = new GreekPizza();
            pizza.setName("GreekPizza");
        } else if ("Cheese".equals(pizzaType)) {
            pizza = new CheesePizza();
            pizza.setName("CheesePizza");
        }
        return pizza;
    }
}

public class OrderPizza {
    String pizzaType = "";
    Pizza pizza = null;
    public OrderPizza() {
        do {
            pizzaType = getType();
            pizza = SimpleFactory.createPizza(pizzaType);
            if (pizza != null) {
                pizza.prepare();
                pizza.bake();
                pizza.cut();
                pizza.box();
            } else {
                break;
            }
        } while(true);
    }
}

public static void main(String[] args) {
    new OrderPizza();
}

工厂方法模式

基本介绍

        定义一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例化推迟到了子类。

实例分析

        针对上述实例,现增加一个新的需求:客户在点披萨时,可以点不同口味的披萨,比如:北京的CheesePizza,北京的PapperPizza或者上海的CheesePizza,上海的PapperPizza。对此需求,可以有如下两个思路进行修改:

思路一:

        使用简单工厂模式,创建不同的简单工厂类,比如:BJPizzaFactory、SHPizzaFactory等等。此方法对当前案例来说,可以使用,但是考虑到项目规模,以及软件的可维护性,可扩展性并不是特别好。(例如:如果有多个PizzaFactory)。

思路二:使用工厂方法模式,将披萨项目的实例化功能抽象成抽象方法,在不同的口味点餐子类中具体实现。

针对思路二,具体实现如下:

新增BJPapperPizza,BJCheesePizza,SHPapperPizza,SHCheesePizza继承Pizza类。

public class BJCheesePizza extends Pizza{
    @Override
    public void prepare() {
        setName("BJCheesePizza");
        System.out.println("prepare BJCheesePizza");
    }
}

public class BJPapperPizza extends Pizza{
    @Override
    public void prepare() {
        setName("BJPapperPizza");
        System.out.println("prepare BJPapperPizza");
    }
}

public class SHCheesePizza extends Pizza {
    @Override
    public void prepare() {
        setName("SHCheesePizza");
        System.out.println("prepare SHCheesePizza");
    }
}


public class SHPapperPizza extends Pizza{
    @Override
    public void prepare() {
        setName("SHPapperPizza");
        System.out.println("prepare SHPapperPizza");
    }
}
// 将订购披萨功能改为抽象化
public abstract class OrderPizza {
    // 提供创建对象的抽象方法
    abstract Pizza createPizza(String pizzaType);
    public OrderPizza() {
        Pizza pizza = null;
        String pizzaType;
        do {
            pizzaType = getType();
            pizza = createPizza(pizzaType);
            pizza.prepare();
            pizza.bake();
            pizza.cut();
            pizza.box();
        } while(true);
    }
}

// 根据不同的需求,在子类中具体实现抽象方法
public class BJOrderPizza extends OrderPizza{
    @Override
    Pizza createPizza(String pizzaType) {
        Pizza pizza = null;
        if ("Cheese".equals(pizzaType)) {
            pizza = new BJCheesePizza();
        } else if ("Papper".equals(pizzaType)) {
            pizza = new BJPapperPizza();
        }
        return pizza;
    }
}

public class SHOrderPizza extends OrderPizza{
    @Override
    Pizza createPizza(String pizzaType) {
        Pizza pizza = null;
        if ("Cheese".equals(pizzaType)) {
            pizza = new SHCheesePizza();
        } else if ("Papper".equals(pizzaType)) {
            pizza = new SHPapperPizza();
        }
        return pizza;
    }
}

// 主方法
public static void main(String[] args) {
    // new BJOrderPizza();
    new SHOrderPizza();
}

对以上所述实例的实现可以进一步使用抽象工厂模式进行修改,具体如下所所述: 

抽象工厂模式

基本介绍

(1)定义一个interface用于创建相关或有依赖关系的对象簇,而无需指明具体的类。

(2)抽象工厂模式可以将简单工厂模式和工厂方法模式进行整合。

(3)从设计层面上看,抽象工厂模式就是对简单工厂模式的改进(或者称为进一步的抽象)。

(4)将工厂抽象为两层,AbsFactory(抽象工厂)和具体实现的工厂子类。程序员可以根据创建对象类型使用对应的工厂子类。这样将单个的简单工厂类变成了工厂簇,更利于代码的维护和扩展。

实例分析

// 添加一个创建实例的抽象工厂
public interface AbsFactory {
    public Pizza createPizza(String orderType);
}

// 根据要求使用具体的工厂子类去实现创建对象的操作
public class BJFactory implements AbsFactory{
    @Override
    public Pizza createPizza(String orderType) {
        Pizza pizza = null;
        if ("Papper".equals(orderType)) {
            pizza = new BJPapperPizza();
        } else if ("Cheese".equals(orderType)) {
            pizza = new BJCheesePizza();
        }
        return pizza;
    }
}

public class SHFactory implements AbsFactory {
    @Override
    public Pizza createPizza(String orderType) {
        Pizza pizza = null;
        if ("Papper".equals(orderType)) {
            pizza = new SHPapperPizza();
        } else if ("Cheese".equals(orderType)) {
            pizza = new SHCheesePizza();
        }
        return pizza;
    }
}

public class OrderPizza {
    public OrderPizza(AbsFactory absFactory) {
        setFactory(absFactory);
    }
    private void setFactory(AbsFactory absFactory) {
        Pizza pizza = null;
        String pizzaType = "";
        do {
            pizzaType = getType();
            pizza = absFactory.createPizza(pizzaType);
            if (pizza != null) {
                pizza.prepare();
                pizza.bake();
                pizza.cut();
                pizza.box();
            }
        } while(true);
    }
}

public static void main(String[] args) {
    // new OrderPizza(new BJFactory());
    new OrderPizza(new SHFactory());
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值