工厂方法(Factory Method)模式
概念:
在创建类的时候,通常可以同时定义多个构造函数,然后利用他们创建类的实例,然而有些时候,客户并不关心对象究竟是从哪个类里面创建而来的,只需要某个对象即可。
工厂方法模式的意图:
定义一个用于创建对象的接口,并控制返回哪个类的实例
注意;工厂模式进一步扩展将在后续进行补充,并不作为本小结重点内容
耦合性
概念:
耦合性(Coupling):也叫耦合度,是对模块间关联程度的度量。耦合的强弱取决于模块间接口的复杂性、调用模块的方式以及通过界面传送数据的多少。模块间的耦合度是指模块之间的依赖关系,包括控制关系、调用关系、数据传递关系。模块间联系越多,其耦合性越强,同时表明其独立性越差( 降低耦合性,可以提高其独立性)。
在软件工程中,耦合指的就是就是对象之间的依赖性。对象之间的耦合越高,维护成本越高。因此对象的设计应使类和构件之间的耦合最小。软件设计中通常用耦合度和内聚度作为衡量模块独立程度的标准。划分模块的一个准则:就是高内聚低耦合。
注意:耦合与内聚进一步解释将在后续进行补充,并不作为本小结重点内容
案例;
使用三层架构的方式(只是用来说明)来阐述为什么要降低耦合度
- dao层
public interface UserDao {
void findAll();
}
public class UserDaoImpl implements UserDao {
@Override
public void findAll() {
System.out.println("dao运行了");
}
}
- service层
public interface UserService {
void findAll();
}
import com.chinasoft.service.UserService;
public class UserServiceImpl implements UserService {
@Override
public void findAll() {
System.out.println("业务层运行了");
}
}
web层
import java.io.IOException;
public class UserWeb {
public static void main(String[] args) throws ClassNotFoundException, IOException, InstantiationException, IllegalAccessException {
UserService userService=new UserServiceImpl();
UserDao userDao=new UserDaoImpl();
userService.findAll();
userDao.findAll();
}
}
由上述源码我们可以看出,每次当我们执行UserDaoImpl或者UserServiceImpl里的方法的时候,我们需要创建new一个UserDaoImpl对象或者UserServiceImpl,但是对于程序本身来说,我们的目的是需要使用这个类里面的方法,对于如何创建、几时创建这个类的对象,我们并不关心。同时,如果我们不创建这个对象,那么我们就无法进行下一步的操作,即无法:userService.findAll(); 在编译器就会报错。这是我们不愿意看到的,我们希望如果有错,在运行期报错而不是编译期。
降低耦合度的思想:
1.利用反射创建对象,避免了使用new关键字2.通过读取配置文件来获取需要的创建的对象的全限定类名
bean.properties配置文件:
userService=com.chinasoft.service.impl.UserServiceImpl
userDao=com.chinasoft.dao.impl.UserDaoImpl
BeanFactory:
import java.io.IOException;
import java.util.*;
/**
* 该类的作用:一个创建Bean对象的工厂类
* 创建servive和dao对象
*/
public class BeanFactory {
protected static Properties pro;//定义一个用于接收properties对象的变量
protected static Map<String,Object> map;//用于存储配置文件里面的对象名和其全限定类名
//静态块在new对象之前就会执行,而且一个类在第一次被使用的时候会被加载,
//然后在整个应用程序的生命周期当中不会再次被加载了,就加载这一次。
static {
try {
//1.读取properties文件
pro=new Properties();
pro.load(BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties"));
//2.获取properties里面的所有Key值
Enumeration<Object> keys=pro.keys();
map=new HashMap<>();//初始化map对象
//判断是否有下一个元素
while(keys.hasMoreElements()){
//nextElement()取出下一个元素
String key=keys.nextElement().toString();
//利用反射动态的创建一个对象
Object bean=Class.forName(pro.getProperty(key)).newInstance();
//将该对象放入map中
map.put(key,bean);
}
} catch (Exception e) {
e.printStackTrace();
}
}
//提供一个方法,用于获取"工厂"中的对象
public static Object getBean(String beanName){
return map.get(beanName);
}
}
修改后的UserWeb:
public class UserWeb {
public static void main(String[] args) throws ClassNotFoundException, IOException, InstantiationException, IllegalAccessException {
UserService userService= (UserService) BeanFactory.getBean("userService");
UserDao userDao= (UserDao) BeanFactory.getBean("userDao");
userDao.findAll();
userService.findAll();
}
}
我们可以看出,在这里我们并没有使用new来创建对象,而是直接从工厂中取,这时候可能就会有人会问,只不过是换了一个地方new 对象,但是,如果我们此时这个地方写的参数不是userService或者userDao(即写的不是配置文件里的key值),那么程序一样不会在编译时期出错,这就是使用工厂模式–(反射+配置文件)设计的好处。