工厂模式
背景:
一般在程序过程中,利用new来创建对象的时候,也就是在具体化一个类。我们一直所提倡的就是针对接口编程,这样就可以让程序不用依赖于具体类的实现,而在运行中动态的绑定来实现多态功能。如果代码是针对接口而写的,那么通过多态,它可以与任何新类实现该接口。但是倘若代码使用大量的具体类的时候,就不利于维护,一旦加入新的具体类的时候,就要修改代码。
一般创建新对象最简单的办法是使用new关键字和具体类。只有在某些场合下,倘若要根据具体的条件来创建不同的类,则此时就需要一个专门用于创建和维护对象的工厂。
工厂模式分为三类:
1)简单工厂模式(Simple Factory)
:不利于产生系列产品,也就是不利于多种类型产品。它主要是在基类由一个对象变量负责实例化所有的具体类,而这些具体类都属于一个相同的类型。
2)工厂方法模式(Factory Method)
:又称为多形性工厂。
它的定义为:定义了一个创建对象的接口或抽象类,但由子类来决定要实例化的类是哪一个。工厂方法让类把实例化推迟到了子类中
。它通过继承父类,在子类中决定创建哪些实例化类。它主要用在当一个类有多个子类,而每一个子类又同时有各自专属的子类,则此时就可以用。
3)抽象工厂模式(Abstract Factory)
:又称
它的定义为:提供了一个借口,用于创建相关或依赖对象的家族,而不需要明确指定具体的类。
为工具箱,产生产品族,但不利于产生新的产品;
一 简单工厂模式
简单工厂模式又称静态工厂方法模式。它存在的目的很简单:定义一个用于创建对象的接口。
在简单工厂模式中,一个工厂类处于对产品类实例化调用的中心位置上,它决定哪一个产品类应当被实例化。
简单工厂模式主要就是在定义了一个工厂对象变量作为类的字段,来产生对象。
先来看看它的组成:
1) 工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑。在java中它往往由一个具体类实现。
2) 抽象产品角色:它一般是具体产品继承的父类或者实现的接口。在java中由接口或者抽象类来实现。
3) 具体产品角色:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。
这三种模式从上到下逐步抽象,并且更具一般性。在简单工厂中,工厂是另一个类的成员变量。
具体说明
:
一个pizza店,可以根据客户的点单而生产不同的Pizza
生产pizza店:
package com.whut.singleton;
//简单工厂模式
public class PizzaStore {
SimplePizzaFactory factory;
public PizzaStore(SimplePizzaFactory factory)
{
this.factory=factory;
}
public Pizza orderPizza(String type)
{
Pizza pizza;
//只能创建某一个类型下的子类
pizza=factory.createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
}
//简单工厂模式
public class PizzaStore {
SimplePizzaFactory factory;
public PizzaStore(SimplePizzaFactory factory)
{
this.factory=factory;
}
public Pizza orderPizza(String type)
{
Pizza pizza;
//只能创建某一个类型下的子类
pizza=factory.createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
}
创建Pizza对象的工厂:
package com.whut.singleton;
import com.whut.factory.NYStyleCheesePizza;
import com.whut.factory.NYStyleClamPizza;
import com.whut.factory.NYStyleVeggiePizza;
import com.whut.factory.Pizza;
public class SimplePizzaFactory {
public Pizza createPizza(String item)
{
Pizza pizza= null;
// TODO Auto-generated method stub
if(item.equals( "cheese"))
pizza= new NYStyleCheesePizza();
else if(item.equals( "veggie"))
pizza= new NYStyleVeggiePizza();
else
pizza= new NYStyleClamPizza();
return pizza;
}
}
import com.whut.factory.NYStyleCheesePizza;
import com.whut.factory.NYStyleClamPizza;
import com.whut.factory.NYStyleVeggiePizza;
import com.whut.factory.Pizza;
public class SimplePizzaFactory {
public Pizza createPizza(String item)
{
Pizza pizza= null;
// TODO Auto-generated method stub
if(item.equals( "cheese"))
pizza= new NYStyleCheesePizza();
else if(item.equals( "veggie"))
pizza= new NYStyleVeggiePizza();
else
pizza= new NYStyleClamPizza();
return pizza;
}
}
二 工厂方法模式
工厂方法让子类决定要实例化的是哪个类,这里的决定并不是让类在运行时决定,而是在编写创建者类的时候,不需要知道实际创建的是哪一个产品。工厂方法其实就是在抽象类中定义了一个产生对象的方法,由具体的子类来实现到底产生什么样的对象。
工厂方法模式是简单工厂模式的进一步抽象化和推广,工厂方法模式里不再只由一个工厂类决定那一个产品类应当被实例化,这个决定被交给抽象工厂的子类去做。
它的组成:
1)抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。
2)具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。
3)抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。
4)具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。
工厂方法模式使用继承自抽象工厂角色的多个子类来代替简单工厂模式中的“上帝类”。这样使得结构变得灵活起来——当有新的产品产生时,只要按照抽象产品角色、抽象工厂角色提供的合同来生成,那么就可以被客户使用,而不必去修改任何已有的代 码。可以看出工厂角色的结构也是符合开闭原则的!
具体实例:
//抽象工厂
public abstract class CarFactory {
abstract Vehicle create();
}
public abstract class CarFactory {
abstract Vehicle create();
}
//具体工厂
public class PlaneFactory extends CarFactory{
public Vehicle create() {
return new Plane();
}
}
//具体工厂
public class BroomFactory extends CarFactory{
public Vehicle create() {
return new Broom();
}
}
public class PlaneFactory extends CarFactory{
public Vehicle create() {
return new Plane();
}
}
//具体工厂
public class BroomFactory extends CarFactory{
public Vehicle create() {
return new Broom();
}
}
//测试类
public class Test {
public static void main(String[] args) {
CarFactory factory = new BroomFactory();
Moveable m = factory.create();
m.run();
}
}
public class Test {
public static void main(String[] args) {
CarFactory factory = new BroomFactory();
Moveable m = factory.create();
m.run();
}
}
工厂方法模式和简单工厂模式在定义上的不同是很明显的。工厂方法模式的核心是一个抽象工厂类,而不像简单工厂模式, 把核心放在一个具体的子类上。工厂方法模式可以允许很多实例工厂类从抽象工厂类继承下来, 从而可以在实际上成为多个简单工厂模式的综合,从而推广了简单工厂模式。
反过来讲,简单工厂模式是由工厂方法模式退化而来。设想如果我们非常确定一个系统只需要一个实的工厂类, 那么就不妨把抽象工厂类合并到实的工厂类中去。而这样一来,我们就退化到简单工厂模式了。
反过来讲,简单工厂模式是由工厂方法模式退化而来。设想如果我们非常确定一个系统只需要一个实的工厂类, 那么就不妨把抽象工厂类合并到实的工厂类中去。而这样一来,我们就退化到简单工厂模式了。
设计原则(依赖倒置原则):要依赖抽象,不要依赖具体类
高层组件和底层组件依赖于一个抽象产品。
在实际开发中,注意几个原则,可以避免违反依赖倒置原则:
1)变量不可以持有具体类的引用。如果使用new,就会持有具体类的引用。
2)不要让类派生自具体类。如果派生于具体类,就会依赖于具体类,一般派生于接口或抽象类。派生具体类会使子类具有一些不要的功能,而派生接口或抽象类,会将共享的部分提出,变化的部分共子类来实现。
3)不要覆盖基类中已经实现的方法。如果覆盖基类已实现的方法,那么基类就不适合被继承,基类实现的方法,应该由子类共享。
小思考 选择抽象类还是接口,一般来说倘若子类都具有一些相同的功能,且功能的具有相同的行为,则使用抽象类,而把相同的功能且具有不同变化的行为交给子类来实现。倘若子类都具全部的功能且行为不同,则就用接口,并且接口可以避免java中的单继承限制特点。
三 抽象工厂模式
它主要是用来创建一系列的产品族,抽象工厂的任务就是定义一个负责创建一组产品的接口。工厂方法其实就是潜伏在抽象工厂里面。
举例说明:
//抽象工厂类
public abstract class AbstractFactory {
public abstract Vehicle createVehicle();
public abstract Weapon createWeapon();
public abstract Food createFood();
}
//具体工厂类,其中Food,Vehicle,Weapon是抽象类,
public class DefaultFactory extends AbstractFactory{
@Override
public Food createFood() {
return new Apple();
}
@Override
public Vehicle createVehicle() {
return new Car();
}
@Override
public Weapon createWeapon() {
return new AK47();
}
}
//测试类
public class Test {
public static void main(String[] args) {
AbstractFactory f = new DefaultFactory();
Vehicle v = f.createVehicle();
v.run();
Weapon w = f.createWeapon();
w.shoot();
Food a = f.createFood();
a.printName();
}
}
public abstract class AbstractFactory {
public abstract Vehicle createVehicle();
public abstract Weapon createWeapon();
public abstract Food createFood();
}
//具体工厂类,其中Food,Vehicle,Weapon是抽象类,
public class DefaultFactory extends AbstractFactory{
@Override
public Food createFood() {
return new Apple();
}
@Override
public Vehicle createVehicle() {
return new Car();
}
@Override
public Weapon createWeapon() {
return new AK47();
}
}
//测试类
public class Test {
public static void main(String[] args) {
AbstractFactory f = new DefaultFactory();
Vehicle v = f.createVehicle();
v.run();
Weapon w = f.createWeapon();
w.shoot();
Food a = f.createFood();
a.printName();
}
}
工厂方法和抽象工厂的比较
工厂方法使用的是类,而抽象工厂使用的是对象。他们都负责创建对象,工厂方法通过继承来让子类来创建具体的实例化类,而抽象工厂则是通过对象的组合来创建,因为抽象工厂要创建一系列的产品族。利用工厂方法来创建对象的时候需要扩展一个类,并且覆盖它的工厂方法。抽象工厂需要一个大基类,这个大基类包括了所有产品的创建的“工厂方法”。
当需要创建产品家族和想让制造的相关产品集合起来,就是用抽象工厂。
当还不知道以后需要实例化哪些类的时候,可以使用工厂方法。
工厂方法,就是一个基类中包含了一个工厂方法,让子类来决定创建哪些自己的类型产品。
抽象工厂,就是一个基类中包含了创建一系列产品的方法,让子类来实例化具体的对象集合。
整体比较:
(1)简单工厂模式是由一个具体类去创建其他类的实例,父类是相同的,父类是具体的。
(2)工厂方法模式是由一个抽象的父类定义的抽象方法,子类负责生成具体的对象,这样做的目的是将类的实例化操作延迟到子类中完成。
(3)抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无须指定他们具体的类。它针对的是有多个产品的等级结构。而工厂方法模式针对的是一个产品的等级结构。
要点
1)所有的工厂都是用来封装对象的创建的
2)工厂方法使用继承:把对象的创建委托给子类,子类实现工厂方法来创建对象
3)抽象工厂使用对象组合:对象的创建被实现在工厂接口所暴露的方法中
4)所有的工厂模式都通过减少应用程序和具体类之间的依赖促进松耦合
5)工厂方法允许将类实例化延迟到子类进行
6)抽象工厂创建相关的对象家族,而不需要依赖于他们的具体类
本文转自 zhao_xiao_long 51CTO博客,原文链接:http://blog.51cto.com/computerdragon/1155657