简单工厂和工厂方法模式的代码实现和区别联系

简单工厂

简单工厂的定义是:由一个工厂对象决定创建出哪一种产品类的实例。

需要注意的是,简单工厂属于创建型,但是却不属于GOF23种设计模式

它的适用场景是:

  1. 工厂类负责创建的对象比较少
  2. 应用层只知道传入工厂类的参数,对于如何创建对象并不关心

所以简单工厂方法也有对应的优点和缺点:

  • 优点:它只需要传入一个正确的参数就能获取对应的对象,而不需要知道其创建的细节
  • 缺点:它的职责相对过重,增加新的产品需要修改工厂类的判断逻辑,违背类开闭的原则

简单工厂实现过程

为了实现简单工厂,我们需要建立一个抽象类,然后让两个真实类继承这个抽象类。

抽象类

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类图如下:可以看见我们的创建主类并不依赖于实体类,只依赖于工厂类

在这里插入图片描述

工厂方法

工厂方法的定义是:定义一个创建对象的接口,但是让实现这个接口的类决定实例化哪个类,工厂方法可以让类的实例化推迟到子类中进行

适用的场景:

  1. 创建对象需要大量重复代码
  2. 应用层只知道传入工厂类的参数,对于如何创建对象并不关心
  3. 一个类通过子类来决定创建哪个对象

所以工厂方法也有对应的优点和缺点:

  • 优点:它只需要传入一个正确的参数就能获取对应的对象,而不需要知道其创建的细节。加入新的产品符合开闭原则,提高可扩展性,这也是简单工厂方法所不能实现的。

  • 缺点:类的个数容易过多,增加复杂度,同时增加类系统抽象性和理解难度

工厂方法代码实现

工厂方法代码是在简单工厂方法上改进实现的。
因为一个类通过子类来决定创建哪个对象,所以我们需要把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();
    }
}

这样子就完成了新的产品的建立

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值