工厂方法模式与抽象工厂模式讲解

 

看来韩顺平老师授课视频,觉得例子讲的较为形象,于是坐下总结,目的是怕自己忘记。

 

 

背景:比如现在有披萨的一个项目:

披萨的种类非常多(LondonPizza伦敦的, BeijingPizza北京的), 不同类别披萨下面还有不同口味(奶酪的,胡椒的)的披萨。披萨的制作过程有比如prepare, bake, cut, box 等。

 

由于简单工厂模式较为简单和容易理解,所以掠过。即一个SimpleFactory类的一个静态方法根据接收的条件,创建出对应的子类对象。

先讲解工厂方法模式:

 

思考一:仍然使用简单工厂模式 ,但是这么多披萨杂在一起,显得层次十分不清晰。

解决:引入一种更好的方法,工厂方法模式。定义了一个创建对象的抽象方法,由子类决定要实例化的类,工厂方法将对象的实例化推迟到子类(就是下面具体的订餐类)。

步骤:

1.创建不同的披萨,这些披萨明显需要实现一个接口或继承一个抽象类。

2.需要一个订餐类,但是这个订餐类只提供一个创建pizza对象的抽象方法。

3.不同类别的订餐子类分别实现这个方法,进行对象创建。

 区别:与简单工厂不一样的地方就是,这边对不同的订餐进行了分类,不同类别的订餐子类进行对象的实例化。将对象的实例化推迟到特定的订餐子类。

 

所以用工厂方法来实现的话,关系图如下:

 

与简单工厂不同的是,这边的BJOrderPizza、LDOrderPizza相当于简单工厂中的SimpleFactory(我这边只是名字取的不够标准,比较场景化,BJOrderPizza、LDOrderPizza虽然没有工厂相关的字眼,但是确实是相当于SimpleFactory简单工厂)。我这边只是在OrderPizza提供一个抽象创建的方法,让更具体的子类BJOrderPizza、LDOrderPizza去创建具体类型的披萨,其实就是不同类型的工厂去创建不同类型的披萨,如果(BJOrderPizza、LDOrderPizza、OrderPizza)=>替换成 SimpleFactory,其实就变成了简单工厂模式。所以工厂方法的实质是将对象的实例化推迟到特定的子类进行。(注:如果是简单工厂的话,在OrderPizza中createPizza方法马上就要返回某个具体的披萨对象,且不能再设置成抽象方法了)。

 

 所以根据上面的关系图把代码实现如下:

 

 Pizza抽象类:

public class PizzaStore {
    public static void main(String[] args) {
        //创建北京奶酪披萨
        BJOrderPizza bjOrderPizza = new BJOrderPizza();
        Pizza cheese = bjOrderPizza.createPizza("cheese");
        cheese.pizzaShow();
        //创建伦敦的胡椒披萨
        LDOrderPizza ldOrderPizza = new LDOrderPizza();
        Pizza pepper = ldOrderPizza.createPizza("pepper");
        pepper.pizzaShow();
    }
}

 

 BJCheesePizza

public class BJCheesePizza extends Pizza {

    @Override
    public void prepare() {
        setName("北京奶酪披萨");
        System.out.println("北京的奶酪披萨准备原材料");
    }

}

 

BJPepperPizza

public class BJPepperPizza extends Pizza {

    @Override
    public void prepare() {
        setName("北京胡椒披萨");
        System.out.println("北京的胡椒披萨准备原材料");
    }

}

 

LDCheesePizza

public class LDCheesePizza extends Pizza {
    @Override
    public void prepare() {
        setName("伦敦奶酪披萨");
        System.out.println("伦敦的奶酪披萨准备原材料");
    }
}

 

LDPepperPizza

public class LDPepperPizza extends Pizza{
    @Override
    public void prepare() {
        setName("伦敦胡椒披萨");
        System.out.println("伦敦的胡椒披萨准备原材料");
    }
}

 

OrderPizza

public abstract class OrderPizza {
    abstract Pizza createPizza(String orderType);
}

 

BJOrderPizza

public class BJOrderPizza extends OrderPizza {
    @Override
    Pizza createPizza(String orderType) {
        Pizza pizza = null;
        if(orderType.equals("cheese")){
            pizza = new BJCheesePizza();
        } else if(orderType.equals("pepper")){
            pizza = new BJPepperPizza();
        }
        return pizza;
    }
}

 

LDOrderPizza

public class LDOrderPizza extends OrderPizza{

    @Override
    Pizza createPizza(String orderType) {
        Pizza pizza = null;
        if(orderType.equals("cheese")){
            pizza = new LDCheesePizza();
        } else if(orderType.equals("pepper")){
            pizza = new LDPepperPizza();
        }

        return pizza;
    }
}

 

PizzaStore

public class PizzaStore {
    public static void main(String[] args) {
        //创建北京奶酪披萨
        BJOrderPizza bjOrderPizza = new BJOrderPizza();
        Pizza cheese = bjOrderPizza.createPizza("cheese");
        cheese.pizzaShow();
        //创建伦敦的胡椒披萨
        LDOrderPizza ldOrderPizza = new LDOrderPizza();
        Pizza pepper = ldOrderPizza.createPizza("pepper");
        pepper.pizzaShow();
    }
}

 

 

 输出:

北京的奶酪披萨准备原材料
北京奶酪披萨baking
北京奶酪披萨cutting
北京奶酪披萨boxing
~~~结束!
伦敦的胡椒披萨准备原材料
伦敦胡椒披萨baking
伦敦胡椒披萨cutting
伦敦胡椒披萨boxing
~~~结束!

 

接下来讲解抽象工厂模式:

 

还是这个案例,抽象工厂模式的关系图,如下:

 

 

 

抽象工厂模式将工厂抽象成两层。AbsFactory(抽象工厂)和具体的工厂子类。可以根据创建对象的类型选择对应的工厂子类。就将当个的简单工厂类变成了工厂簇。有利于代码的维护和拓展。(这个是面向接口编程的独到优势)。so, 抽象工厂可以看作是简单工厂和工厂方法模式的整合。这种整合并不是单纯的代码叠加,是一种思想的体现。例如关系图BJFactory和LDFactory就相当于简单工厂模式中的工厂实例。AbsFactory和BJFactory、LDFactory的关系就是类似于工厂方法模式中体现的功能下沉,将对象的实例化推迟到子类。最终这个AbsFactory聚合到一个订餐类中,传递依赖后,供使用。

 

根据上面的关系图, 代码实现如下:

其中:Pizza、BJCheesePizza、BJPepperPizza、LDCheesePizza、LDPepperPizza跟工厂方法模式是一样的,掠过。

 

AbsFactory:

public interface AbsFactory {
    public Pizza createPizza(String orderType);
}

 

BJFactory(跟工厂方法模式的BJOrderPizza内部实现是一致的):

public class BJFactory implements AbsFactory {
    @Override
    public Pizza createPizza(String orderType) {
        Pizza pizza = null;
        if(orderType.equals("cheese")){
            pizza = new BJCheesePizza();
        } else if(orderType.equals("pepper")){
            pizza = new BJPepperPizza();
        }
        return pizza;
    }
}

 

LDFactory(跟工厂方法模式的LDOrderPizza内部实现是一致的):

public class LDFactory implements AbsFactory {
    @Override
    public Pizza createPizza(String orderType) {
        Pizza pizza = null;
        if(orderType.equals("cheese")){
            pizza = new LDCheesePizza();
        } else if(orderType.equals("pepper")){
            pizza = new LDPepperPizza();
        }
        return pizza;
    }
}

 

OrderPizza:

public class OrderPizza {
    AbsFactory absFactory;

    public void setAbsFactory(AbsFactory absFactory) {
        this.absFactory = absFactory;
    }

    public Pizza getPizza(String orderType){
        return absFactory.createPizza(orderType);
    }
}

 

客户端PizzaStore:

public class PizzaStore {
    public static void main(String[] args) {
        OrderPizza orderPizza1 = new OrderPizza();
        orderPizza1.setAbsFactory(new BJFactory());
        Pizza cheese = orderPizza1.getPizza("cheese");
        cheese.pizzaShow();
        OrderPizza orderPizza2 = new OrderPizza();
        orderPizza2.setAbsFactory(new LDFactory());
        Pizza pepper = orderPizza2.getPizza("pepper");
        pepper.pizzaShow();
    }
}

 

posted @ 2019-03-15 23:47  护花使者  Views(201)  Comments(0Edit  收藏  举报