错误的理解了简单工厂模式

首先说明一下,这篇文章的理解会有很多的问题,可能你刚刚学习工厂模式容易走进的一个误区,我就走进来了。

看完了这篇文章之后,大家可以看看另一篇文章,这是我的新的认识:http://blog.csdn.net/tayanxunhua/article/details/10297013


我这里通过代码说说简单工厂模式,大家都知道简单工厂模式的定义:根据传入的参数即可返回所需的对象,而不需要知道具体类的类名。

再说一下优缺点:


优点:

1、客户端或者说调用者,不需要知道对象是如何创建的,只管用就可以了,减少了调用者的记忆量(不需要记住类名嘛);


2、通过工厂实现了责任的分割;


3、通过引入配置文件,可以实现在不修改源代码的情况下,更换或添加新的具体产品类(注意:这里我指的是已有产品类的具体类,稍后会解释)。


缺点:

1、工厂类的职责过多,一旦工厂类出现问题,就会影响到整个系统;


2、增加系统中类的个数,进而增加了系统的复杂度;


3、系统扩展比较困难,如果添加新的产品类(如:我添加和已有的产品类(TV类)不同的产品类(Fruit类)),此时就需要更改工厂类中的方法了,因为之前工厂类中只有getTV的静态工厂方法,而没有getFruit的静态工厂方法,所以,只能添加一个这样的静态工厂方法了(这是对前面的解释)。当然了,如果添加TV的具体类(如:TCLTV,然后实现TV类,那么这不违反开闭原则);


4、简单工厂模式使用了静态工厂方法,这就造成了我这个工厂无法形成基于继承的等级结构。举例说明:我现在的工厂类负责生产TV产品,如果我希望通过继承的方法实现,即我有一个总工厂的虚拟类(定义了所有的工厂类),每一个具体的工厂类需要继承这个总的工厂类,而那个总的工厂类中定义了静态的工厂方法,同时它的每个子类同样定义了这个方法,这就会导致这样的问题:定义的时候使用的是父类,实例化的是子类(这样的格式:SuperClass sub  =  new SubClass(); ),我无法使用子类中的静态方法去创建想要的对象,每次调用的方法都是总工厂类中的静态方法。(因为子类不能重写父类中的静态方法),这回差不多理解了吧;


5、违反了开闭原则,原因可以参考第3条。补充:违反开闭原则的原因不是因为添加已经存在的产品类(如实现TV类的TCLTV类,这里不需要修改工厂类的代码,不过很多资料说简单工厂违反开闭原则是这个原因,我觉得静态工厂方法里面通过反射机制实现对象的创建),而是因为添加新的产品类(如新建一个Fruit接口,然后AppliFruit类实现接口,这样就必须修改工厂类的代码了,其实我认为简单工厂违反开闭原则是这个原因


好了上代码吧:

package com.tyxh.pattern.sample;

public interface TV {

        public void play();
}


package com.tyxh.pattern.sample;

public class HaierTV implements TV {

        @Override
        public void play() {
                System.out.println("Haier TV");
        }

}


package com.tyxh.pattern.sample;

public class HisenseTV implements TV {

        @Override
        public void play() {
                System.out.println("Hisense TV");
        }

}


package com.tyxh.pattern.sample;

public class TVFactory {
        
        public static TV getTV(String name) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
                TV tv = (TV) Class.forName("com.tyxh.pattern.sample." + name).newInstance();
                return tv;
                
//              if (name.equals("Haier")) {
//                      return new HaierTV();
//              } else if (name.equals("Hisense")) {
//                      return new HisenseTV();
//              } else {
//                      return null;
//              }
        }
        
}


package com.tyxh.pattern.sample;

import java.io.File;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class XMLUtil {
        public static String getBrandName() {
                try {
                        //创建文档对象
                        DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
                        DocumentBuilder builder = dFactory.newDocumentBuilder();
                        Document doc = builder.parse(new File("src/com/tyxh/pattern/sample/config.xml"));
                        
                        //获取节点
                        NodeList nl = doc.getElementsByTagName("brandName");
                        Node classNode = nl.item(0).getFirstChild();
                        String brandName = classNode.getNodeValue().trim();
                        return brandName;
                } catch(Exception e) {
                        e.printStackTrace();
                        return null;
                }
                
        }
}


<!--config.xml-->
<?xml version="1.0"?>
<config>
        <brandName>TyxhTV</brandName>
</config>


package com.tyxh.pattern.sample;

public class Client {

        public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
                String brandName = XMLUtil.getBrandName();
                TV tv = TVFactory.getTV(brandName);
                tv.play();
        }
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值