简单工厂
简单工厂的定义是:由一个工厂对象决定创建出哪一种产品类的实例。
需要注意的是,简单工厂属于创建型,但是却不属于GOF23种设计模式
它的适用场景是:
- 工厂类负责创建的对象比较少
- 应用层只知道传入工厂类的参数,对于如何创建对象并不关心
所以简单工厂方法也有对应的优点和缺点:
- 优点:它只需要传入一个正确的参数就能获取对应的对象,而不需要知道其创建的细节
- 缺点:它的职责相对过重,增加新的产品需要修改工厂类的判断逻辑,违背类开闭的原则
简单工厂实现过程
为了实现简单工厂,我们需要建立一个抽象类,然后让两个真实类继承这个抽象类。
抽象类
public abstract class Databases {
public abstract void run();
}
真实类
public class Mysql extends Databases {
@Override
public void run() {
System.out.println("Mysql服务开启");
}
}
public class Redis extends Databases {
@Override
public void run() {
System.out.println("Redis服务开启");
}
}
我们先来看一下如果没有简单工厂,我们平时是如何创建这些对象的
我们会直接利用new关键字来创建对应的对象,这样的缺点是非常依赖于外部类,需要import对应的包
//非简单工厂创建方式
public class Test {
public static void main(String[] args) {
Databases database = new Redis();
database.run();
}
}
所以我们需要创建一个简单工厂类来实现创建,这个工厂方法是根据参数的字符串来判断创建什么样的对象
public class DatabasesFactory {
public static Databases createFactory(String args){
if (args.equalsIgnoreCase("Mysql")){
return new Mysql();
}
else if(args.equalsIgnoreCase("Redis")){
return new Redis();
}
return null;
}
}
所以我们只需要利用以下的代码来实现简单工厂的创建即可
public class Test {
public static void main(String[] args) {
Databases database = DatabasesFactory.createFactory("Redis");
if (database!=null){
database.run();
}
}
}
结果如下:
Redis服务开启
简单工厂类的创建方法可以进一步改为利用反射来获取实例对象
public class DatabasesFactory {
public static Databases createFactory(Class c){
Databases databases = null;
try {
databases = (Databases) Class.forName(c.getName()).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return databases;
}
}
简单工厂对应的UML类图如下:可以看见我们的创建主类并不依赖于实体类,只依赖于工厂类
工厂方法
工厂方法的定义是:定义一个创建对象的接口,但是让实现这个接口的类决定实例化哪个类,工厂方法可以让类的实例化推迟到子类中进行
适用的场景:
- 创建对象需要大量重复代码
- 应用层只知道传入工厂类的参数,对于如何创建对象并不关心
- 一个类通过子类来决定创建哪个对象
所以工厂方法也有对应的优点和缺点:
-
优点:它只需要传入一个正确的参数就能获取对应的对象,而不需要知道其创建的细节。加入新的产品符合开闭原则,提高可扩展性,这也是简单工厂方法所不能实现的。
-
缺点:类的个数容易过多,增加复杂度,同时增加类系统抽象性和理解难度
工厂方法代码实现
工厂方法代码是在简单工厂方法上改进实现的。
因为一个类通过子类来决定创建哪个对象,所以我们需要把DatabasesFactory变成一个抽象类
public abstract class DatabasesFactory {
public abstract Databases createFactory();
}
然后我们还需要实现DatabasesFactory的两个子类,让他们实现创建对应的实例
//Mysql工厂
public class MysqlFactory extends DatabasesFactory {
@Override
public Databases createFactory() {
return new Mysql();
}
}
//Redis工厂
public class RedisFactory extends DatabasesFactory {
@Override
public Databases createFactory() {
return new Redis();
}
}
所以创建一个实例的过程如下:
public class Test {
public static void main(String[] args) {
DatabasesFactory databasesFactory = new MysqlFactory();
Databases databases = databasesFactory.createFactory();
databases.run();
}
}
我们可以查看他们的类图以及依赖关系
工厂方法与简单工厂比较最大的优点就是它的可拓展性,比如现在我们需要新增新的产品,在简单工厂中我们需要添加判断的语句else if 来进一步排除判断,这样很容易出现错误。而工厂方法只需要添加新的工厂子类即可
比如我们现在要新添加一个产品MongoDB,过程如下:
新建MongoDB类:
public class MongoDB extends Databases {
@Override
public void run() {
System.out.println("MongoDB服务开启");
}
}
新建MongoDB工厂类继承DatabasesFactory,实现createFactory()方法创建实例
public class MongoDBFactory extends DatabasesFactory {
@Override
public Databases createFactory() {
return new MongoDB();
}
}
这样子就完成了新的产品的建立