设计模式笔记(四)--工厂方法模式、抽象工厂模式

工厂模式(Factory Pattern)

    (1)简单工厂(Simple Factory)

应该都注意到了,这里没有使用模式(Pattern)的字眼,因为简单工厂更像是一种编程习惯,而不是严格意义上的设计模式。

先说一下客户类怎么使用:直接Pizza pizza = PizzaFactory.createPizza("cheese");就可以获得CheesePizza类型的披萨了(PizzaFactory的静态方法createPizza()中仅仅return new CheesePizaa();而已)。

再看一下涉及的角色:

工厂类角色:具体类,有一个根据不同参数创建不同对象的静态方法(也就是上面的createPizza),并返回该对象父类型对象。

抽象产品角色:接口/抽象类,是所有产品的抽象(就是Pizza)。

具体产品角色:具体类,是工厂中要new的具体对象(就是CheesePizza)。

简单点说,就是把创建对象的任务独立出来,让一个专门的类去负责创建,我们只需告诉这个类要创建对象的类型就能拿到该类型的对象了。

    (2)工厂方法模式(Factory Method Pattern)

定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个,工厂方法让类把实例化推迟到子类。

设计模式笔记(四)--工厂方法模式、抽象工厂模式_第1张图片

其中的“工厂方法”就是用来实例化具体产品的。

这样,原本由一个对象负责所有具体类的实例化,现在由一群子类来实例化了。

在客户类中我们可以看到:Pizza pizza = createPizza(type); ...  protected abstract Pizza createPizza(String type);实例化Pizza的责任被移到一个“方法中”,还是一个没有实现的方法(由子类实现),该方法就像是一个“工厂”,可以创建对象,在超类中我们可以直接利用这个方法的返回对象,而不用管这个对象的具体实例化类型。

这样,客户程序(超类)的代码和子类创建对象的代码就解耦了。

Notes:

依赖倒置原则:要依赖抽象,不要依赖具体类

避免违反依赖倒置原则:①变量不要持有具体类的引用(不能直接new) ②不要派生自具体类(最好派生抽象) ③不要覆盖基类中已经实现的方法

    (3)抽象工厂模式(Abstract Factory Pattern)

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

简单点说,就是定义一个抽象的工厂类,其不同子类生产不同的产品族的产品。如果还不懂,下面的类图可以便于理解。

设计模式笔记(四)--工厂方法模式、抽象工厂模式_第2张图片

用抽象的接口来创建一组相关的产品,这就是抽象工厂模式的目的。

先说一下背景:一个披萨(Pizza)店需要创建一个Pizza,当然Pizza是多种多样的。首先Pizza说我需要一个原料工厂来创建我需要的原料,而原料又分为面团、酱料、蔬菜肉等等,而面团又可分为薄的和厚的,酱料也分大蒜番茄酱和李子形番茄酱等等。位于纽约的原料工厂只生产符合纽约人口味的薄面团和大蒜番茄酱原料,位于芝加哥的原料工厂也只生产芝加哥口味的厚面团和李形番茄酱原料。而对于一个具体的Pizza,当我需要原料时我就从原料工厂中拿就行了,我不关心具体是哪个原料工厂,我只关心怎么制作Pizza(准备、烘烤、切片、装箱)。这里Pizza和具体原料就解耦了,是不是很帅啊。

对于客户,如纽约Pizza店,要制作Pizza,先要有一个原料工厂来供应原料,它当然选择纽约风味Pizza原料工厂作为自己的Pizza原料工厂,然后就可以利用这个原料工厂创建比如芝士Pizza等不同Pizza了。

还要了解两个概念:“产品等级结构”和“产品族”。产品等级结构是指不同产品的层次结构,例如这里的厚面团和薄面团是相同的等级结构,大蒜番茄酱和李子形番茄酱也是相同的等级结构,但面团和番茄就是不同的等级结构了。产品族是指位于不同产品等级中功能相关联的产品组成的家族,例如这里的薄面团和大蒜番茄酱组成了纽约风味原料家族,而厚面团和李形番茄酱组成了芝加哥风味原料家族。所以每个具体工厂创建一组产品族产品。从抽象工厂派生出的具体工厂生产相同的产品,但是产品的实现不同。

    最后,还是要比较一下工厂方法模式和抽象工厂模式:

都是负责创建对象,将客户从具体类型中解耦。

工厂方法用的是继承,而抽象工厂用的是对象组合。

工厂方法是创建一个产品,而抽象工厂是创建整个产品家族。



你可能感兴趣的:(Java,设计模式,工厂模式,工厂方法模式,抽象工厂模式)