工厂模式java实现

程序的耦合

耦合性(Coupling),也叫耦合度,是对模块间关联程度的度量。耦合的强弱取决于模块间接口的复杂性、调用模块的方式以及通过界面传送数据的多少。模块间的耦合度是指模块之间的依赖关系,包括控制关系、调用关系、数据传递关系。模块间联系越多,其耦合性越强,同时表明其独立性越差( 降低耦合性,可以提高其独立性)。耦合性存在于各个领域,而非软件设计中独有的,但是我们只讨论软件工程中的耦合。

在软件工程中,耦合指的就是就是对象之间的依赖性。对象之间的耦合越高,维护成本越高。因此对象的设计应使类和构件之间的耦合最小。软件设计中通常用耦合度和内聚度作为衡量模块独立程度的标准。划分模块的一个准则就是高内聚低耦合。
它有如下分类:
(1) 内容耦合。当一个模块直接修改或操作另一个模块的数据时,或一个模块不通过正常入口而转入另一个模块时,这样的耦合被称为内容耦合。内容耦合是最高程度的耦合,应该避免使用之。
(2) 公共耦合。两个或两个以上的模块共同引用一个全局数据项,这种耦合被称为公共耦合。在具有大量公共耦合的结构中,确定究竟是哪个模块给全局变量赋了一个特定的值是十分困难的。
(3) 外部耦合。一组模块都访问同一全局简单变量而不是同一全局数据结构,而且不是通过参数表传递该全局变量的信息,则称之为外部耦合。
(4) 控制耦合。一个模块通过接口向另一个模块传递一个控制信号,接受信号的模块根据信号值而进行适当的动作,这种耦合被称为控制耦合。
(5) 标记耦合。若一个模块 A 通过接口向两个模块 B 和 C 传递一个公共参数,那么称模块 B 和 C 之间 存在一个标记耦合。
(6) 数据耦合。模块之间通过参数来传递数据,那么被称为数据耦合。数据耦合是最低的一种耦合形式,系统中一般都存在这种类型的耦合,因为为了完成一些有意义的功能,往往需要将某些模块的输出数据作为另
一些模块的输入数据。
(7) 非直接耦合 。两个模块之间没有直接关系,它们之间的联系完全是通过主模块的控制和调用来实现的。

耦合是影响软件复杂程度和设计质量的一个重要因素,在设计上我们应采用以下原则:如果模块间必须存在耦合,就尽量使用数据耦合,少用控制耦合,限制公共耦合的范围,尽量避免使用内容耦合。

内聚与耦合

内聚标志一个模块内各个元素彼此结合的紧密程度,它是信息隐蔽和局部化概念的自然扩展。内聚是从功能角度来度量模块内的联系,一个好的内聚模块应当恰好做一件事。它描述的是模块内的功能联系。耦合是软件结构中各模块之间相互连接的一种度量,耦合强弱取决于模块间接口的复杂程度、进入或访问一个模块的点以及通过接口的数据。程序讲究的是低耦合,高内聚。就是同一个模块内的各个元素之间要高度紧密,但是各个模块之间的相互依存度却要不那么紧密。

内聚和耦合是密切相关的,同其他模块存在高耦合的模块意味着低内聚,而高内聚的模块意味着该模块同其他模块之间是低耦合。在进行软件设计时,应力争做到高内聚,低耦合。

工厂模式解耦

在实际开发中我们可以把表示层,业务逻辑层,持久层的对象都使用配置文件配置起来,当启动服务器应用加载的时候,让工厂类通过读取配置文件,把这些对象创建出来并存起来。在接下来的使用的时候,直接拿过来用就好了。

下面的例子中我们将尽量避免使用new关键字来创建对象。

持久层接口IStudentDao

package dao;
/**
 * 持久层接口
 */
public interface IStudentDao {
    /**
     * 模拟查询所有
     */
    void findAll();
}

持久层实现类StudentDaoImpl

package dao.impl;

import dao.IStudentDao;

/**
 * 持久层实现类
 */
public class StudentDaoImpl implements IStudentDao {

    @Override
    public  void findAll(){
        System.out.println("查找到所有学生记录。");
    }
}

业务逻辑层接口IStudentService

package service;
/**
 * 业务层的接口
 */
public interface IStudentService {
    /**
     * 模拟查询
     */
    void findAll();
}

业务逻辑层实现类StudentServiceImpl

package service.impl;

import dao.IStudentDao;
import dao.impl.StudentDaoImpl;
import factory.BeanFactory;
import service.IStudentService;

/**
 * 业务层实现类
 */
public class StudentServiceImpl implements IStudentService {

    private IStudentDao studentDao = (StudentDaoImpl)BeanFactory.getBean("studentDao");
    @Override
    public void  findAll(){
        studentDao.findAll();
    }
}

配置文件bean.properties

studentDao=dao.impl.StudentDaoImpl
studentService=service.impl.StudentServiceImpl

工厂类BeanFactory

package factory;

import java.io.InputStream;
import java.util.*;

/**
 *   一个创建Bean对象的工厂
 *   需要一个配置文件来配置我们的service和dao
 *   配置的内容:唯一标识=全限定类名(key=value)
 *   通过读取配置文件中配置的内容,反射创建对象
 *	 配置文件可以是xml也可以是properties
 */
public class BeanFactory {
    //定义一个Properties对象
    private static Properties props;
    //定义一个Map,用于存放我们要创建的对象。我们把它称之为容器
    private static Map<String,Object> beans;
    //使用静态代码块为Properties对象赋值
    static {
        try {
            //实例化对象
            props = new Properties();
            //获取properties文件的流对象
            InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
            props.load(in);
            //实例化容器
            beans = new HashMap<String,Object>();
            //取出配置文件中所有的Key
            Set<String> keys = props.stringPropertyNames();
            //遍历枚举
            for (String key : keys) {
                //根据key获取value
                String beanPath = props.getProperty(key);
                //反射创建对象
                Object value = Class.forName(beanPath).getDeclaredConstructor().newInstance();
                //把key和value存入容器中
                beans.put(key,value);
            }
        }catch(Exception e){
            throw new ExceptionInInitializerError("初始化properties失败!");
        }
    }
    /**
     * 根据bean的名称获取对象
     * @param beanName
     * @return
     */
    public static Object getBean(String beanName){
        return beans.get(beanName);
    }
}

该工厂会将dao和service对象存入容器(map)中,需要对象时只需要调用工厂类静态方法getBean,传入相应key,即可获得对应对象,并且每一个类所创建的对象是唯一的,实现了单例模式。
测试类

import factory.BeanFactory;
import service.IStudentService;
import service.impl.StudentServiceImpl;
/**
 * 模拟一个表现层,用于调用业务层
 */
public class Client {

    public static void main(String[] args) {
        IStudentService as = (StudentServiceImpl)BeanFactory.getBean("studentService");
        IStudentService as1 = (StudentServiceImpl)BeanFactory.getBean("studentService");
        System.out.println(as==as1);
        as.findAll();
    }
}

输出结果如下:

true
查找到所有学生记录。

Process finished with exit code 0

以上就是今天分享的内容了,欢迎关注。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值