设计模式之工厂模式

1. 简单工厂

根据客户端传入的参数进行判断,再决定创建哪种实例,缺点很明显:

  • 传参错误则不能创建正确的实例
  • 扩展需要修改工厂方法

2.工厂方法

在工厂类中定义若干的函数来创建实例,每个函数创建一种实例,解决的简单工厂需要传参的问题

3. 静态工厂方法

3.1 定义

将工厂类中的工厂方法定义为静态类型,使用静态工厂不需要创建工厂实例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class SendFactory {  

public static Sender produceMail(){
return new MailSender();
}

public static Sender produceSms(){
return new SmsSender();
}
}
public class FactoryTest {

public static void main(String[] args) {
Sender sender = SendFactory.produceMail();
sender.Send();
}
}

(静态)工厂方法缺点是:

  • 对于扩展需要修改工厂类

3.2 用静态工厂方法代替构造器(Effective java:rule 1)

如果不通过共有构造器,或者说除了公有构造器之外,类还可以给他的客户端提供静态工厂方法,这样做既有优势又有劣势。
优势在于:

  • 第一点:它们有名称。使客户端代码更容易阅读,例如:构造器BigInteger(int,int,Random)返回的BigInteger可能是素数,如果用静态工厂方法BigInteger.probablePrime来表示,就会更清楚。
  • 第二点:不必每次调用的时候都创建一个新对象。静态工厂方法能够为重复的调用返回相同的对象
  • 第三点:静态工厂方法可以返回类型的任何子类型对象,构造器则做不到这一点。
  • 第四点:每次调用返回对象的类可以变化,取决于静态工厂方法的参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//该代码 解释以上四点优势
public class Child {
protected String classId;
public Child(){
classId = "CHILD";
}
public static class Son extends Child {
public Son(){ classId = "SON"; }
}
public static class Daughter extends Child {
public Daughter(){ classId = "DAUGHTER"; }
}

public static Child sonFactory(){
return new Son();
}
public static Child daughterFactory(){
return new Daughter();
}
public static Child childFactory(int sex){
return sex == 1 ? new Son() : new Daughter();
}
public static void main(String[] args){
Child son = Child.sonFactory();
Child child = Child.childFactory(2);
System.out.println(son.classId + "\n" + child.classId);
}
}
  • 第五点:方法返回对象的类,在编写包含该静态方法的类时是可以不存在的。
    第五点的灵活性是构成服务提供者框架(Service Provider Framework)的基础,将另起一片单独研究。

静态工厂方法的劣势在于:

  • 程序员很难发现这些静态工厂方法。
  • 类如果没有公有或者受保护的构造器,就不能被子类化(不允许被继承)。

4.抽象工厂

对每一个需要创建实例的类都配置了一个工厂类,需要扩展的时候,增加一个工厂类,实现工厂类的抽象方法进行实例创建,实现了开闭原则。