Java-设计模式-工厂模式浅谈(二)-工厂方法模式

来源:互联网 发布:最新软件开发方法 编辑:程序博客网 时间:2024/06/06 12:41

再上一篇文章 Java-设计模式-工厂模式浅谈(一)-简单工厂模式 中,我们使用工厂模式,对情景进行了实现。
下面我们从开闭原则(对扩展开放;对修改封闭)上来分析下简单工厂模式。

情景再现
在哪个市举办了《中国好嗓门》歌唱比赛,报名者络绎不绝,想要在图爱上一展歌喉。在海选期间,报名者们被要求自报家门,说说自己叫什么名字,做什么职业。(我也很奇怪,为什么不让他们说说自己是哪人,多少岁。。。可能只想知道名字和职业吧。。。。)

当前来报名的人不再满足现有的职业的时候,想要创建一个新的职业的时候,只要这种职业符合抽象产品中的要求(有姓名,有职业),那么只要通知工厂类知道,就可以被创建了。
所以对产品部分来说,它是符合开闭原则的;但是工厂部分好像不太理想,因为每增加一种新的职业,都要在工厂类中增加相应的创建业务逻辑(createPeople(String str,String name) 方法需要新增case),有可能会改错代码,造成不必要的损失,这显然是违背开闭原则的。
对于这样的工厂类,我们称它为全能类或者上帝类
但如果有更多的职业加入进来,就一定要增加更多的职业类和switch中的case选择。可想而知对于新产品的加入,工厂类是很被动的。
我们将工厂类定义成接口,而每新增的职业类型,就增加该职业类型对应工厂类的实现,这样工厂的设计就可以扩展了,而不必去修改原来的代码。

于是工厂方法模式出现了。

工厂方法模式去掉了简单工厂模式中工厂方法的静态属性,使得它可以被子类继承。这样在简单工厂模式里集中在工厂方法上的压力可以由工厂方法模式里不同的工厂子类来分担。

工厂方法模式组成:    1)抽象工厂角色:这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。    2)具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。    3)抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。    4)具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。 

正如上面所说,这样便分担了对象承受的压力;而且这样使得结构变得灵 活 起来——当有新的产品产生时,只要按照抽象产品角色、抽象工厂角色提供的合同来生成,那么就可以被客户使用,而不必去修改任何已有 的代码。可以看出工厂角色的结构也是符合开闭原则的!

工厂方法模式使用继承自抽象工厂角色的多个子类来代替简单工厂模式中的“上帝类”。

抽象工厂角色
现在,我们将每个产品对应的工厂类中相同的地方抽象出来,做成工厂接口Factory。
Factory

package 工厂方法模式;public interface Factory {    People createPeople();//抽象方法    People createPeople(String name);}

具体工厂角色
每种职业对应的工厂,都去调用工厂Factory接口。重写创建实例的方法createPeople()
StudentFactory

package 工厂方法模式;public class StudentFactory implements Factory {    @Override    public Student createPeople() {        return new Student();    }    @Override    public People createPeople(String name) {        return new Student(name);    }}

TeacherFactory

package 工厂方法模式;public class TeacherFactory implements Factory {    @Override    public Teacher createPeople() {        return new Teacher();    }    @Override    public People createPeople(String name) {        return new Teacher(name);    }}

NurseFactory

package 工厂方法模式;public class NurseFactory implements Factory{    @Override    public People createPeople() {        return null;    }    @Override    public Nurse createPeople(String name) {        return new Nurse(name);    }}

抽象产品角色
现在,我们将学生,教师和护士共有的属性和方法抽象出来,
做成一个类,这就是抽象产品角色

package 工厂方法模式;abstract class People {    public People(){        System.out.println("People类创建成功");    }    private String name;    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public void say(){        System.out.println("People类");    }    public People(String name) {        this.name=name;    }}

具体产品角色
接下来是 具体的角色:学生,教师,护士类的创建。在这里,去继承People。这些子类就是具体产品角色

Student

package 工厂方法模式;public class Student extends People{    public Student(){        System.out.println("Student类创建成功");    }    @Override    public void say(){        System.out.println("我是一名学生,我叫"+this.getName());    }    public Student(String name){        System.out.println("Student类创建成功");        this.setName(name);    }}

Teacher

package 工厂方法模式;public class Teacher extends People{    public Teacher(){        System.out.println("Teacher类创建成功");    }    @Override    public void say(){        System.out.println("我是一名教师,我叫"+this.getName());    }    public Teacher(String name){        System.out.println("Teacher类创建成功");        this.setName(name);    }}

Nurse

package 工厂方法模式;public class Nurse extends People {    public Nurse(){        System.out.println("Nurse类创建成功");    }    @Override    public void say(){        System.out.println("我是一名护士,我叫"+this.getName());    }    public Nurse(String name){        System.out.println("Nurse类创建成功");        this.setName(name);    }}

最后创建启动方法RunFromHere进行测试

package 工厂方法模式;public class RunFromHere {    public static void main(String[] args) {        StudentFactory student = new StudentFactory();        People stu = student.createPeople("小阿花");        stu.say();        TeacherFactory teacher = new TeacherFactory();        People tea = teacher.createPeople("小阿花");        tea.say();        NurseFactory nurse = new NurseFactory();        People nur = nurse.createPeople("小阿花");        nur.say();    }}

测试结果
工厂方法模式

通过上面的例子,
只要有新的职业加入进来,我们只需要添加职业类和职业工厂类。
就可以在启动方法中直接使用了。
不用去修改代码,大大增强了安全性。

阅读全文
0 0
原创粉丝点击