软件设计 简单工厂模式:Simple Factory
1、定义水果类
/**
* 水果类
*/
public class Fruit {
private final String name;
public Fruit(String name){
this.name = name;
}
}
2、定义苹果类
/**
* 苹果类
*/
public class Apple extends Fruit{
public Apple() {
super("苹果");
}
}
3、定义橘子类
/**
* 橘子类
*/
public class Orange extends Fruit{
public Orange() {
super("橘子");
}
}
4、定义水果工厂
/**
* 水果工厂
*/
public class FruitFactory {
/**
* 这里就直接来一个静态方法根据指定类型进行创建
* @param type 水果类型
* @return 对应的水果对象
*/
public static Fruit getFruit(String type) {
switch (type) {
case "苹果":
return new Apple();
case "橘子":
return new Orange();
default:
return null;
}
}
}
5、调用
// 直接问工厂要,而不是自己去创建
Apple apple = (Apple) FruitFactory.getFruit("苹果");
Orange orange = (Orange) FruitFactory.getFruit("橘子");
此时如果需要新增一种水果,比如桃子,那么就得去修改工厂提供的工厂方法了,这样是不太符合开闭原则的。因为工厂实际上是针对于调用方提供的,所以应该尽可能对修改关闭。
工厂方法模式
/**
* 水果类
*/
public class Fruit {
private final String name;
public Fruit(String name){
this.name = name;
}
}
1、定义水果工厂
/**
* 水果工厂
* <p>将水果工厂抽象为抽象类,添加泛型 T 由子类指定水果类型
*/
public abstract class FruitFactory<T extends Fruit> {
/**
* 不同的水果工厂,通过此方法生产不同的水果
* @return 水果对象
*/
public abstract T getFruit();
}
2、定义苹果工厂
/**
* 苹果工厂
*/
public class AppleFactory extends FruitFactory<Apple>{
/**
* 获取苹果对象
* @return 苹果对象
*/
这样,就简单实现了工厂方法模式,通过工厂来屏蔽对象的创建细节,使用者只需要关心如何去使用对象即可
优缺点:
优点
1、一个调用者想创建一个对象,只要知道其名称就可以了。
2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。
3、屏蔽产品的具体实现,调用者只关心产品的接口。
缺点
每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。
使用场景:
1、日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。
2、数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。
3、设计一个连接服务器的框架,需要三个协议,”POP3”、”IMAP”、”HTTP”,可以把这三个作为产品类,共同实现一个接口。
注意:
作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new
就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。