解决方案1:工厂模式
可以使用抽象工厂模式,让StudentDao、StudentService的实现在在工厂中生成,而工厂可以根据配置 文件的指定类型来创建不同的对象,而且工厂本身一般是不变的。从而降低了对可以变的业务逻辑类的 依赖,接近的软件的设计目标”高内聚,低耦合”。控制层-->抽象工厂-->业务逻辑层
public class StudentAction {
/*依赖具体的对象改为依赖工厂, 而工厂创建的路径来自具体的配置文件,所以灵活性大大提高.
* 必须要声明为接口类型,否则工厂没有任何意义(面向接口编程)
* /
private StudentService studentService=
(StudentService)BeanFactory.getBean("studentService");
private Student student;
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
public String save() {
studentService.save(student);
return "success";
}
}
业务逻辑层-----抽象工厂-----数据访问层
public class StudentServiceImpl implements StudentService {
// 依赖工厂,降低耦合度,可以根据配置灵活修改创建的对象
private StudentDao studentDao=
(StudentDao)BeanFactory.getBean("studentDao");
public void save(Student student) {
studentDao.save(student);
}
}
以上代码就是通过抽象工厂来实现层与层之间的解耦,这种情况下如果想要更新别外一个实现类,只需要修改配置文件就可以了,注意这里只是降低了层与层之间的复杂度,并没有让耦合消失,实际上层与层是不可能没有耦合的。学框架的目标就是要找到变的部分,然后用配置文件来配置这样修改的时候修改配置文件就OK了, 不需要修改代码本身。但是有时候有些类创建的时候需要单例模式, 有的则需要多个实例、还有不同的类在创建的时候有些类需要初始化操作, 有些又不需要初始化数据…..这又怎么办呢?那就要再完善一下这个工厂类了, 或者多创建一些工厂了. 让工厂可以处理这些问题, 但是我们自己实现起来就复杂了
工厂模式
工厂模式
Factory Pattern
是
Java
中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提 供了一种创建对象的最佳方式。在工厂模式中,在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
意图
:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程
延迟到子类进行。
public class StudentAction {
/*依赖具体的对象改为依赖工厂, 而工厂创建的路径来自具体的配置文件,所以灵活性大大提高.
* 必须要声明为接口类型,否则工厂没有任何意义(面向接口编程)
* /
private StudentService studentService=
(StudentService)BeanFactory.getBean("studentService");
private Student student;
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
public String save() {
studentService.save(student);
return "success";
}
}
public class StudentServiceImpl implements StudentService {
// 依赖工厂,降低耦合度,可以根据配置灵活修改创建的对象
private StudentDao studentDao=
(StudentDao)BeanFactory.getBean("studentDao");
public void save(Student student) {
studentDao.save(student);
}
}
主要解决
:主要解决接口选择的问题。
何时使用
:我们明确地计划不同条件下创建不同实例时。
优点:
1
、一个调用者想创建一个对象,只要知道其名称就可以了。
2
、扩展性高,如果想增加一
个产品,只要扩展一个工厂类就可以。
3
、屏蔽产品的具体实现,调用者只关心产品的接口。
缺点:
每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增
加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。

接口
public interface Shape{
public void draw();
}
多种实现
public class Circle implements Shape{}
public class Square implements Shape{}
public class Rectangle implements Shape{}
最终目标还是需要使用某个实现,但是为了解除耦合引入工厂类,传递工厂类一个名称,由工厂类封装 了具体的创建对象流程
public class ShapeFactory {
//使用 getShape 方法获取形状类型的对象
public Shape getShape(String shapeType){
if(shapeType == null) return null;
if(shapeType.equalsIgnoreCase("CIRCLE")){
return new Circle();
} else if(shapeType.equalsIgnoreCase("RECTANGLE")){
return new Rectangle();
} else if(shapeType.equalsIgnoreCase("SQUARE")){
return new Square();
}
return null;
}}
调用
Shape
类型的对象时,调用方并不需要了解具体的实现类,只需要一个名称参数即可
public class Test{
public static void main(String[] args){
Shape shape=ShapeFactory.getShape("circle");
shape.draw():
}
}
这个模式最大的优势在于允许产品扩展
public class MyShape implements Shape{} --- 新产品
扩展产品只需要添加一个对应的工厂类即可
public class MyFactory extends ShapeFactory{
public Shape getShape(String shapeType){
if("my".equalsIgnoreCase(shapeType))
return new MyShape();
else
return super.getShape(shapeType);
}
}
产品可以扩展,但是产品的系列不可扩展,同时可以会导致类爆炸问题