省掉工厂也是可以实现多态以解耦。
下面的例子是参考别人的博客,连接放在最下面了。
eg:
package factory;
public interface Leifeng {
void sweep();
void wash();
void buyRice();
}
//实现类
package factory;
public class Student implements Leifeng {
private String name;
public Student(String name){
this.name = name;
}
@Override
public void sweep() {
System.out.println(name+"扫地(大学生)");
}
@Override
public void wash() {
System.out.println(name+"洗菜");
}
@Override
public void buyRice() {
System.out.println(name+"买米");
}
}
package factory;
public class Volunteer implements Leifeng {
private String name;
public Volunteer(String name){
this.name = name;
}
@Override
public void sweep() {
System.out.println(name+"扫地(志愿者)");
}
@Override
public void wash() {
System.out.println(name+"洗菜");
}
@Override
public void buyRice() {
System.out.println(name+"买米");
}
}
//工厂
package factory;
public interface IFactory {
Leifeng createLeiFeng(String name);
}
//工厂实现类
package factory;
public class StudentFactory implements IFactory {
@Override
public Student createLeiFeng(String name) {
return new Student(name);
}
}
package factory;
public class VolunteerFactory implements IFactory {
@Override
public Leifeng createLeiFeng(String name) {
return new Volunteer(name);
}
}
//测试类
package factory;
public class Test {
public static void main(String[] args) {
IFactory factory = new StudentFactory();
Leifeng l = factory.createLeiFeng("张三");
IFactory factory1 = new VolunteerFactory();
Leifeng ll = factory1.createLeiFeng("李四");
l.sweep();
ll.sweep();
}
}
这样可以实现增添新的Leifeng实现类不需要更改已有的生产类,只要新增对应的工厂即可。
但是为什么要增加工厂类的实现呢?
直接在测试类里创建你想要类的不可以吗?答案是可以的,你可以直接在测试类中创建student类或者volunteer类。
这个例子确实是可以直接这么做的,从而达到和工厂方法实现一样的效果,而且代码量更少。
工厂模式的特点在于其把类型的“定义过程”和"实例化过程"分离开,也就是在类自身的构造器之外,附加一个经常被误认为没有什么卵用的”工厂类“。当一个类有多种实现类的时候,我们需要使用工厂类来隔离实例化过程。
class ServiceFactory{
Service getService(){
if(a)
Service sA = new ServiceA();
if(b)
Service sB = new ServiceB();
}
}
但是这好像依旧不是使用这个设计模式的根本原因,如果用户输入了生成service的条件,为何不在主类里面直接使用if条件判断并生成呢?为何还要创建一个工厂?这是要把这部分功能给抽取出来,我的理解是实现单一原则,每个类执行一个特定的功能,这样来实现去耦合。为何要把功能单一分割出来?这是要降低风险,保证安全。例如你把两个功能模块写在一个类里,这样的话,如果其实一个功能出现问题,你在修改bug的同时,意味着你可以得到另一个功能的源码,并且你可以更改。这样带来一些风险,所以要创建工厂将创建服务的功能抽取出来,这样创建服务这地方如果需要新增服务,只需要给你工厂类的实现就可以了。上例是简单工厂实现,简单工厂的缺点是当你每次新增服务时都需要修改ServiceFactory,工厂方法实现,则是将servicefactory抽象为一个接口,然后为每一种服务都创建一个实现该接口工厂,这样新增服务时就不需要修改ServiceFactory这个类,而是新增工厂类了。(如果只有一个工厂,不同的service在不同环境下有不同的实现,如果环境很多,则实现很多,而且每种实现可能是不同组的人实现的,如果都写在一个类内,则变量可能冲突,而且别的组的人修改他们的实现改变一些变量,可能影响我们自己的实现,所以才有了工厂方法模式,这样每组人只需要修改他们自己实现的工厂类即可。)
而且在《Think in Java》中,作者提出”组合优先于继承“(好处参考状态模式),利用多态,状态模式可以在runtime改变内部组件的类型,从而改变类的行为,更加灵活。
而且这是其一,其二是更根本的原因。
在这里,service并没有给出具体实现,所以看不出工厂太大的作用,只会让人感觉代码量增多了,好处不明显。但是如果service很复杂呢?现在我们脱离开service那个例子,假设我们现在要创建一个机器,这个机器很复杂,由很多组件组装而成,如果我们把这些都写在一个类里,那么这个机器类的内容就是各个组件成员变量,机器的行为,以及在构造器中定义机器的组装流程。如果这个机器很复杂,那么构造方法就会特别复杂,而且由于单一原则,机器应该只负责怎么使用,而不用管机器是怎怎么产生的,所以,我们把构造器单独提取出来,即把机器的创建流程提取出来,从而形成了工厂类。实现了机器构建与机器的去耦。
除以上两点,还有第三点。
如果student和volunteer类或者service占用资源特别多呢?你还可以在一上来就直接创建吗?那么你可能会说我们在需要他们的时候再创建不就好了,反正使用工厂类也是在需要的时候再去创建的,那我们在需要使用这些service类的时候直接创建service不就好了? 那我再问,如果service服务需要在多个地方使用呢?或者需要很多实例化对象分布在不同的位置,比如需要创建十个服务分布在程序的各个位置,那样如果需要修改服务,你怎么办呢? 把这十处找出来挨个修改吗?(因为很多服务创建的时候需要很多参数,如果有一个参数需要修改,那么你就要把所有创建实例的地方都找出来挨个修改),这时候你如果提前把所有要用到的实例都创建好,则回到了第一个问题,如果这些类占用资源很多,就会造成资源浪费。所以结合原因2,工厂类的好处我想已经不言而喻了吧。可以在工厂类中把创建服务所需要的参数准备好,然后当需要修改的时候,只需要修改工厂类对应的参数值,而其他的地方的创建语句等等,完全不需要修改。而且工厂类仅仅只是定义了一些创建服务所需要的参数,占用资源很少,所以可以提前创建。而且工厂类实现了1对多,1个工厂类可以生产无数该类服务。适应service创建不固定的情形。所以,这就是为什么需要工厂模式。
以上全为个人理解,如果有错误或者理解不当的地方,请大佬们指正。
参考博文:https://www.zhihu.com/question/30351872