Java设计模式之工厂模式分析【简单工厂、工厂方法、抽象工厂】
本文实例讲述了Java设计模式之工厂模式。分享给大家供大家参考,具体如下:
一、简单工厂
先来思考一个问题。我们平时写程序时,会有这种情况,A对象里面需要调用B对象的方法,这时我们使用的一般是new关键字来创建一个B实例,然后调用B实例的方法。这种做法的坏处在于:A类的方法实现直接调用了B类的类名(这种方式也被称为硬编码耦合),一旦系统需要重构:需要使用C类来代替B类时,程序就不得不修改A类代码,如果应用中有100个或者10000个类以硬编码方式耦合了B类,则需要修改100个、10000个地方,这显然是一种非常可怕的事情。
换一个角度来看这个问题:对已A对象而言,它只需要调用B对象的方法,并不关心B对象的实现、创建过程,考虑让B类实现一个IB接口,而A类只需要与IB接口耦合——A类并不直接使用new关键字来创建B实例,而是重新定义一个工厂类:IBFactory,由该工厂类负责创建IB实例,而A类用过调用IBFactory工厂的方法来得到IB的实例。通过以上设计:需要使用C类代替B类,则只需要让C类也实现IB接口,并改写IBFactory工厂中创建IB实例的实现代码,让该工厂产生C实例即可。这种将多个类对象交给工厂类来生成的设计方式叫做简单工厂模式。
以下是简单工厂模式的代码:
/**
*简单工厂模式
*
*需要工厂生产的对象实例所实现的共同的接口
*发型接口
*@authorAdministrator
*
*/
publicinterfaceHair{
/**
*画发型
*/
publicvoiddraw();
}
/**
*左偏分发型
*@authorAdministrator
*
*/
publicclassLeftHairimplementsHair{
@Override
publicvoiddraw(){
System.out.println("----------------画左偏分发型-----------------");
}
}
/**
*右偏分发型
*@authorAdministrator
*
*/
publicclassRightHairimplementsHair{
@Override
publicvoiddraw(){
System.out.println("-----------------画右偏分发型------------------");
}
}
/**
*生产发型的工厂
*要生产什么发型只需在这里改就行了
*@authorAdministrator
*
*/
publicclassHairFactory{
publicHairgetHair(){
returnnewLeftHair();
//returnnewRightHair();
}
}
/**
*客户端测试类
*@authorAdministrator
*
*/
publicclassHairTest{
publicstaticvoidmain(String[]args){
HairFactoryfactory=newHairFactory();
Hairhair=factory.getHair();
hair.draw();
}
}
可以看到,如果想把HairTest里面生成的LeftHair改成RightHair,只需修改HairFactory里面getHair方法的实现即可。
使用简单工厂模式的优势在于:让对象的调用者和对象的创建过程分离,当对象调用者需要对象时,直接向工厂请求即可,从而避免了对象的调用者与对象实现类以硬编码方式耦合,以提高系统的可维护性、可扩展性。当然,工厂模式也有一个小小的缺陷,当产品修改时,工厂类也要做相应的修改,此处可使用策略模式进行解决,下面是代码。
publicinterfaceHairBuilder{
/**
*制造发型
*@return
*/
publicHairgetHair();
}
publicclassLeftHairBuilderimplementsHairBuilder{
@Override
publicHairgetHair(){
returnnewLeftHair();
}
}
publicclassRightHairBuilderimplementsHairBuilder{
@Override
publicHairgetHair(){
returnnewRightHair();
}
}
publicclassHairFactory{
privateHairBuilderhairBuilder;
publicHairFactory(HairBuilderhairBuilder){
this.hairBuilder=hairBuilder;
}
publicvoidsetHairBuilder(HairBuilderhairBuilder){
this.hairBuilder=hairBuilder;
}
publicHairgetHair(){
returnhairBuilder.getHair();
}
}
publicclassHairTest{
publicstaticvoidmain(String[]args){
//HairBuilderbuilder=newLeftHairBuilder();
HairBuilderbuilder=newRightHairBuilder();
HairFactoryfactory=newHairFactory(builder);
Hairhair=factory.getHair();
hair.draw();
}
}
这种做法的好处是无需再去修改工厂类,将工厂里面的创建对量逻辑根据不同的策略抽象出来,程序需要创建什么对象,只需网工厂中传入相应的builder即可。
二、工厂方法
在简单工厂模式中,系统使用工厂类生产所有产品实例,且该工厂类决定生产哪个类的实例,即工厂类负责所有的逻辑判断、实例创建等工作。
如果不想再工厂类中进行逻辑判断,程序可以为不同的产品类提供不同的工厂,不同的工厂类生产不同的产品,无需再工厂类中进行复杂的逻辑判断。这就有点类似于上面的简单工厂模式结合策略模式,不同的是前者只有一个工厂,后者需要有多个工厂。下面是工厂方法模式的代码。
/**
*工厂方法模式
*需要工厂生产的对象实例所实现的共同的接口
*@authorAdministrator
*
*/
publicinterfacePerson{
publicvoiddrawPerson();
}
publicclassManimplementsPerson{
@Override
publicvoiddrawPerson(){
System.out.println("---------------------drawaman--------------------");
}
}
publicclassWomenimplementsPerson{
@Override
publicvoiddrawPerson(){
System.out.println("--------------------drawawomen---------------------");
}
}
/**
*生产人的工厂
*@authorAdministrator
*
*/
publicinterfacePersonFactory{
//生产人
publicPersongetPerson();
}
/**
*生产man的工厂
*@authorAdministrator
*
*/
publicclassManFactoryimplementsPersonFactory{
@Override
publicPersongetPerson(){
returnnewMan();
}
}
/**
*声场women的工厂
*@authorAdministrator
*
*/
publicclassWomenFactoryimplementsPersonFactory{
@Override
publicPersongetPerson(){
returnnewWomen();
}
}
/**
*客户端测试类
*@authorAdministrator
*
*/
publicclassPersonTest{
publicstaticvoidmain(String[]args){
//PersonFactoryfactory=newManFactory();
PersonFactoryfactory=newWomenFactory();
Personperson=factory.getPerson();
person.drawPerson();
}
}
这种的典型的特点就是在客户端代码中根据不同的工厂生产其对应的产品,不必把复杂的逻辑都放在工厂类里面判断。这种实现有一个很明显的缺陷,就是客户端与工厂类进行了耦合。
三、抽象工厂
采用上面的工厂方法的设计架构,客户端代码成功与被调用对象的实现类分离,但带来了另一种耦合:客户端代码与不同的工厂类耦合。为了解决这种耦合的问题,考虑在增加一个工厂类,用来生成工厂实例,实现生产产品的工厂与客户端分离,这种设计方式被称为抽象工厂模式。下面是抽象工厂模式的代码
/**
*抽象工厂模式
*生产PersonFactory的工厂
*@authorAdministrator
*
*/
publicclassPersonFactoryFactory{
publicstaticPersonFactorygetPersonFactory(Stringtype){
if(type.equalsIgnoreCase("man")){
returnnewManFactory();
}else{
returnnewWomenFactory();
}
}
}
/**
*客户端测试类
*@authorAdministrator
*
*/
publicclassPersonTest{
publicstaticvoidmain(String[]args){
PersonFactoryfactory=PersonFactoryFactory.getPersonFactory("man");
Personperson=factory.getPerson();
person.drawPerson();
}
}
更多java相关内容感兴趣的读者可查看本站专题:《Java数据结构与算法教程》、《Java操作DOM节点技巧总结》、《Java文件与目录操作技巧汇总》和《Java缓存操作技巧汇总》
希望本文所述对大家java程序设计有所帮助。