目录
1.概述
- 工厂模式属于创建型设计模式中的一种,用来实例化多个对象,工厂模式分为简单工厂模式、抽象工厂模式、工厂模式。
2.简单工厂模式
2.1没使用之前的问题
- 这里以添加学生为例,使用三层架构中的service处理添加学生业务(以MySQL驱动实现),示例如下: 这样写是我们经常会想到的书写方式------> 有什么问题呢??
public class StudentServiceImpl implements StudentService{
//抽象依赖实现---->固定需更改(不符合原则: 开闭原则 依赖倒置原则)
private StudentDao studentDao=new StudentDaoMySQLImpl();
@Override
public void addStudent() {
studentDao.addStudent();
}
}
- 答:使用抽象直接依赖实现,倒置耦合性增强,而且不符合开闭原则,如何换一个驱动实现方法,如oracle,就必须要更改而不是扩展,也不符合依赖倒置原则(面向接口编程).
- 解决StudentServiceImpl类的问题: 简单工厂模式
2.2 简单工厂
- 简单工厂模式: 定义了一个创建对象的类,由这个类封装实例化对象的行为
- 简单工厂包含的角色:
工厂、抽象产品、具体产品
StudentServiceImpl类
- 1. 使用set 或构造方法将StudentDao 封装,定义它的接口,让实现依赖抽象
- 2. 将多种创建的对象和实现封装到简单工厂中
public class StudentServiceImpl implements StudentService{
//定义接口: 实现依赖抽象
private StudentDao studentDao;
//利用set 方法传递任意实现
public void setStudentDao(StudentDao studentDao) {
this.studentDao = studentDao;
}
@Override
public void addStudent() {
studentDao.addStudent();
}
}
静态工厂类
- 使用场景:在软件开发中,当我们会用到大量的创建某种、某类或某批对象时,就会使用工厂模式
public class StudentFactory {
public static StudentDao getInstance(String key)
{
StudentDao studentDao=null;
switch (key)
{
case "mysql":
studentDao=new StudentDaoMySQLImpl();
break;
case "sqlServer":
studentDao=new StudentDaoSqlServerImpl();
break;
}
return studentDao;
}
}
Test测试类
- 使用简单工厂只需实现修改key 值
public class Test {
public static void main(String[] args) {
//使用set 让StudentService 不依赖实现,降低耦合
//缺点: StudentService将耦合性抛到了Test第三方: 还是不符合开闭原则,没达成解耦
//解决: 使用简单工厂将每种对象都实现
StudentServiceImpl studentService=new StudentServiceImpl();
StudentDao studentDao=new StudentDaoSqlServerImpl();
studentService.setStudentDao(studentDao);
studentDao.addStudent();
//2.使用简单工厂,减少修改,降低耦合性
StudentDao studentDao1=StudentFactory.getInstance("mysql");
studentDao1.addStudent();
}
}
优点 : 工厂类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例。(即每个类的职责不同)
简单工厂的进一步问题:
1. Test将解耦的问题又抛给了静态工厂,如果增加其他数据库的实现,那么还需要再这个基础上,修改,增加,(不符合开闭原则)。
2.由于工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。
3.抽象工厂模式
- 抽象工厂模式:定义了一个interface用于创建相关或有一俩关系的对象簇,而无需指明具体的类。
- 抽象工厂模式划分的角色
1.抽象工厂
2.具体工厂类
3.具体产品类
- 实现思路: 可以将每个不同的产品分别定义他们的工厂类,根据指定工厂创建实例。
- AbstactFactory抽象工厂
: 负责定义所有具体工厂类的方法 如: 创建实例
/**
* 抽象工厂类
*/
public interface AbstractFactory {
//面向接口: 创建实例返回对象
StudentDao getInstance();
}
- MySQL 的具体工厂类
/**
* 针对MySQL的工厂类
*/
public class StudentMySqlFactory implements AbstractFactory {
/**
*重写抽象工厂类的方法--->根据不同的工厂创建不同的产品
* @return
*/
@Override
public StudentDao getInstance() {
return new StudentDaoMysqlImpl();
}
- Sql Server的具体工厂类
/**
* 针对SQlServer的工厂类
*/
public class StudentSQlServerFactory implements AbstractFactory {
/**
*重写抽象工厂类的方法--->根据不同的工厂创建不同的产品
* @return
*/
@Override
public StudentDao getInstance() {
return new StudentDaoSqlServerImpl();
}
}
- MySQL具体产品类
/**
*
* MySQl具体产品类
*/
public class StudentDaoMySQLImpl implements StudentDao {
@Override
public void addStudent() {
System.out.println("使用MySQL增加学生...");
}
}
- Test 测试类
public class Test {
public static void main(String[] args) {
//使用抽象工厂模式
//针对MySQL的实现方式
StudentDao studentDao1= new StudentDaoMySQLFactory().getInstance();
studentDao1.addStudent();
//针对SQLServer的实现方式
StudentDao sqlserver = new StudentDaoSQlServerFactory().getInstance();
sqlserver.addStudent();
}
}
优点:
1.抽象工厂模式将每个具体产品都分离,互不影响,他们各自都有一套工厂类,针对工厂类再去调用具体产品类.
2.当项目中增加新的功能时,只需扩展新的工厂类即可,无需像简单工厂一样修改实例。
缺点: 在扩展新类型的产品灵活性不是很好
4.工厂方法模式
- 工厂方法模式: 将需要实例化的内容定义为抽象方法.
- 定义了一个创建对象的抽象方法,由子类决定要实例化的类.工厂模式将对象的实例化推迟到子类。
- 类似于抽象工厂模式,不过没有定义抽象工厂类,只是定义了一个抽象方法
5.工厂模式小结
5.1工厂模式的意义
- 将实例化对象的代码提取出来,放到一个类中统一管理和维护,达到和主项目的依赖关系解耦,从而提高项目的扩展性和维护性。
- 三种工厂模式(简单工厂模式、工厂方法模式、抽象工厂模式)
5.2 设计模式的依赖抽象原则
- 创建对象实例时,不要直接new类、而是把这个new类的动作放在一个工厂方法中,并返回。
- 不要让类继承具体类,而是继承抽象类或者是interface接口