设计模式之工厂方法模式

工厂方法模式

参照的blog:走传java的23种设计模式
维基百科:工厂方法

概念

工厂

在面向对象程序设计中,工厂通常是一个用来创建其他对象的对象。工厂是构造方法的抽象,用来实现不同的分配方案。
工厂对象通常包含一个或多个方法,用来创建这个工厂所能创建的各种类型的对象。这些方法可能接收参数,用来指定对象创建的方式,最后返回创建的对象。
有时,特定类型对象的控制过程比简单地创建一个对象更复杂。在这种情况下,工厂对象就派上用场了。工厂对象可能会动态地创建产品对象的类,
或者从对象池中返回一个对象,或者对所创建的对象进行复杂的配置,或者应用其他的操作。
这些类型的对象很有用。几个不同的设计模式都应用了工厂的概念,并可以使用在很多语言中

工厂方法模式

工厂方法模式(英语:Factory method pattern)是一种实现了“工厂”概念的面向对象设计模式。就像其他创建型模式一样,
它也是处理在不指定对象具体类型的情况下创建对象的问题。工厂方法模式的实质是“定义一个创建对象的接口,但让实现这个
接口的类来决定实例化哪个类。工厂方法让类的实例化推迟  到子类中进行。”创建一个对象常常需要复杂的过程,所以不适合包含在
一个复合对象中。创建对象可能会导致大量的重复代码,可能会需要复合对象访问不到的信息,也可能提供不了足够级别的抽象,还可能并
不是复合对象概念的一部分。工厂方法模式通过定义一个单独的创建对象的方法来解决这些问题。由子类实现这个方法来创建具体类型的对象。
对象创建中的有些过程包括决定创建哪个对象、管理对象的生命周期,以及管理特定对象的创建和销毁的概念。

UML类图

工厂方法模式

应用场景

1.需要灵活、可扩展的框架
2.在异构的项目中
3.在测试驱动开发的框架中使用
4.可以和其他模式混用(如:单例模式、原型模式)
5.如果你有一个可执行多态的继承层次结构,请考虑通过在基类中定义一个静态工厂方法来添加多态创建功能

优缺点

优点

1.封装性良好
2.可扩展性优秀
3.屏蔽了产品类
4.工厂方法模式是典型的解耦框架

缺点

  • 待完成

代码实例

(1) 工厂的抽象接口BenzFactory

1
2
3
4
5
6
/**
* 抽象工厂类接口
*/
public interface BenzFactory {
Benz createCar();
}

(2) 产品的抽象接口Benz

1
2
3
4
5
6
7
8
/**
* 抽象类接口
*/
public interface Benz {
void carColor();
void carSpeed();
void carPrice();
}

(3) 生产C180的实际工厂

1
2
3
4
5
6
public class C180Factory implements BenzFactory {
@Override
public Benz createCar() {
return new BenzC180();
}
}

(4) 生产B260的实际工厂

1
2
3
4
5
6
public class B260Factory implements BenzFactory {
@Override
public Benz createCar() {
return new BenzB260();
}
}

(5) 生产C180的实际类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class BenzC180 implements Benz {

public BenzC180(){
carColor();
carPrice();
carSpeed();
}

@Override
public void carColor() {
System.out.println("green");
}

@Override
public void carSpeed() {
System.out.println("999迈");
}

@Override
public void carPrice() {
System.out.println("666元");
}
}

(6) 生产B260的实际类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class BenzB260 implements Benz {

public BenzB260(){
carColor();;
carPrice();
carSpeed();
}

@Override
public void carColor() {
System.out.println("red");
}

@Override
public void carSpeed() {
System.out.println("80迈");
}

@Override
public void carPrice() {
System.out.println("100块");
}
}

(7) 测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class TestDemo {
public static void main(String[] args) {
System.out.println("开始创建C180");
C180Factory benzC180 = new C180Factory();
benzC180.createCar();
System.out.println("=======================");
System.out.println("开始创建B260");
B260Factory b260Factory = new B260Factory();
b260Factory.createCar();
System.out.println("=======================");
System.out.println("创建完成");

}
}

上面就是工厂方法模式的基本雏形

工厂方法模式变种

虽然工厂方法模式的背后动机是允许子类选择创建对象的具体类型,但是使用工厂方法模式也有一些其他的好处,
其中很多并不依赖于子类。因此,有时候也会创建不使用多态性创建对象的工厂方法,以得到使用工厂方法的其他好处。

工厂”方法”而不是工厂”类”

如果抛开设计模式的范畴,“工厂方法”这个词也可以指作为“工厂”的方法,这个方法的主要目的就
是创建对象,而这个方法不一定在单独的工厂类中。这些方法通常作为静态方法,定义在方法所实
例化的类中。

每个工厂方法都有特定的名称。在许多面向对象的编程语言中,构造方法必须和它所在的类具有相同的名称,
这样的话,如果有多种创建对象的方式(重载)就可能导致歧义。工厂方法没有这种限制,所以可以具有描述性的名称。
举例来说,根据两个实数创建一个复数,而这两个实数表示直角坐标或极坐标,如果使用工厂方法,
方法的含义就非常清晰了。当工厂方法起到这种消除歧义的作用时,构造方法常常被设置为私有方法,
从而强制客户端代码使用工厂方法创建对象。

下面的例子展示了在编程语言中实现复数创建的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
class Complex {
public static Complex fromCartesianFactory(double real, double imaginary) {
return new Complex(real, imaginary);
}
public static Complex fromPolarFactory(double modulus, double angle) {
return new Complex(modulus * cos(angle), modulus * sin(angle));
}
private Complex(double a, double b) {
//...
}
}

Complex product = Complex.fromPolarFactory(1, pi);

UML类图

工厂方法