工厂模式与抽象工厂模式
来源:互联网 发布:施耐德网络面板接线图 编辑:程序博客网 时间:2024/06/01 21:52
在软件设计中,工厂模式和抽象工厂模式是比较常用的两种模式。下面来对其分别进行介绍。
一、工厂模式
工厂方法模式继承了简单工厂模式的优点,也弥补了简单工厂模式的缺点,符合了“开闭原则”。如果不清楚什么是简单工厂模式,不用担心,接下来所讲的内容不会涉及简单工厂模式。
工厂模式的基本原则是:工厂父类负责创建产品对象的公共接口,而工厂子类来负责生产具体的产品对象。
是不是有点抽象,下面我们直接来看一个例子。
上图是一个UML类图,实现了一个最基本的工厂模式。其中Client是客户类,当它需要生产鞋的时候,会去调用ShoeFactory中的produceShoes()
方法。
而鞋厂(ShoeFactory)本身是能生产男鞋(MaleShoes)和女鞋(FemaleShoes)的,因此在这里必然会使用到多态,即在ShoeFactory下还有两个子工厂(MaleShoesFactory和FemaleShoesFactory),子工厂负责创建真正的产品对象,而父工厂只负责提供一个接口。而当客户需要生产鞋的时候,只需申明一个ShoeFactory的变量指向一个MaleShoesFactory或者FemaleShoesFactory的对象即可。
然而如果仅仅是这样,仍旧是不符合开闭原则的,当需要生产男鞋或女鞋时我们仍然需要去修改代码,但是在此,我们引入了一个神奇的东西:利用DOM和java的反射,设计一个XML文件,保存需要新生成的类名,而再设计一个XML操作工具类XMLUtil,即可实现在程序运行时才能动态获取所需要生成的类。
是不是还是很抽象,没关系,看完代码就明白了。
下面是上面UML类图的实现代码。
先放上代码结构图:
Shoes
public interface Shoes { public void wear();}
MaleShoes
public class MaleShoes implements Shoes{ @Override public void wear() { System.out.println("Wear Male Shoes"); }}
FemaleShoes
public class FemaleShoes implements Shoes{ @Override public void wear() { System.out.println("Wear Female Shoes"); }}
ShoeFactory
public interface ShoeFactory { public Shoes produceShoes();}
MaleShoesFactory
public class MaleShoesFactory implements ShoeFactory{ @Override public Shoes produceShoes() { System.out.println("Produce Male Shoes"); return new MaleShoes(); }}
FemaleShoesFactory
public class FemaleShoesFactory implements ShoeFactory { @Override public Shoes produceShoes() { System.out.println("Produce Female Shoes"); return null; }}
XMLUtil
import javax.xml.parsers.*;import org.xml.sax.SAXException;import java.io.*;import org.w3c.dom.*;public class XMLUtil { public static Object getBean(){ try{ //创建DOM文档对象 DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = dFactory.newDocumentBuilder(); Document doc; doc = builder.parse(new File("config.xml")); //获取包含类名的文本节点 NodeList nl = doc.getElementsByTagName("className"); Node classNode = nl.item(0).getFirstChild(); String cName = classNode.getNodeValue(); //通过类名生成实例对象并将其返回 Class c = Class.forName(cName); Object obj = c.newInstance(); return obj; }catch(Exception e){ e.printStackTrace(); return null; } }}
config.xml
<?xml version="1.0" encoding="UTF-8"?><config> <className>com.zk.factory.MaleShoesFactory</className></config>
接下来就可以运行Client类进行试验了
public class Client { public static void main(String[] args) { try{ Shoes shoes; ShoeFactory factory; factory = (ShoeFactory) XMLUtil.getBean(); shoes = factory.produceShoes(); shoes.wear(); }catch(Exception e){ System.out.println(e.getMessage()); } }}
运行结果为:
可以看见,程序正确执行并创建了MaleShoesFactory的实例,并成功调用了其produceShoes()
方法和wear()
方法。
需要注意的是,在XML配置文件中,如果xml文件不和java代码保存在同一个包下,一定要记得加上包名,否则可能会出现类名找不到的错误。
二、抽象工厂模式
前面讲了工厂模式,有没有发现其还是有缺点,比如说鞋厂只能生产同一款鞋,而设想下一家代加工的鞋厂,里面可能既加工Adidas的鞋,同时还加工Nike的鞋,或者再想想,Nike和Adidas公司在生产鞋的同时,都还在生产衣服,那么,这种情况用工厂模式就不能做到了,因此产生了抽象工厂模式。
抽象工厂模式的适用范围比工厂模式更加广泛,它与工厂模式最大的区别在于:
工厂模式中一个工厂只能生产一种产品,而抽象工厂可以生产多个。
下面来看一个例子:
这里有一家劳工工厂,里面分别为Nike和Adidas代加工产品,而Nike和Adidas都需要该厂为其加工衣服和鞋子。
下面放上代码:
这是代码结构图:
Shoes
public interface Shoes { public void wear();}
AdidasShoes
public class AdidasShoes implements Shoes{ @Override public void wear() { System.out.println("Wear Adidas Shoes"); }}
NikeShoes
public class NikeShoes implements Shoes{ @Override public void wear() { System.out.println("Wear Nike Shoes"); }}
Clothes
public interface Clothes { public void wear();}
NikeClothes
public class NikeClothes implements Clothes{ @Override public void wear() { System.out.println("Wear Nike Clothes"); }}
AdidasClothes
public class AdidasClothes implements Clothes{ @Override public void wear() { System.out.println("Wear Adidas Clothes"); }}
LabourFactory
public interface LabourFactory { Shoes produceShoes(); Clothes produceClothes();}
NikeFactory
public class NikeFactory implements LabourFactory{ @Override public Shoes produceShoes() { System.out.println("Produce Nike Shoes"); return new NikeShoes(); } @Override public Clothes produceClothes() { System.out.println("Produce Nike Clothes"); return new NikeClothes(); }}
AdidasFactory
public class AdidasFactory implements LabourFactory{ @Override public Shoes produceShoes() { System.out.println("Produce Adidas Shoes"); return new AdidasShoes(); } @Override public Clothes produceClothes() { System.out.println("Produce Adidas Clothes"); return new AdidasClothes(); }}
XMLUtil
import javax.xml.parsers.*;import org.xml.sax.SAXException;import java.io.*;import org.w3c.dom.*;public class XMLUtil { public static Object getBean(){ try{ //创建DOM文档对象 DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = dFactory.newDocumentBuilder(); Document doc; doc = builder.parse(new File("config_abstract.xml")); //获取包含类名的文本节点 NodeList nl = doc.getElementsByTagName("className"); Node classNode = nl.item(0).getFirstChild(); String cName = classNode.getNodeValue(); //通过类名生成实例对象并将其返回 Class c = Class.forName(cName); Object obj = c.newInstance(); return obj; }catch(Exception e){ e.printStackTrace(); return null; } }}
config_abstract.xml
<?xml version="1.0" encoding="UTF-8"?><config> <className>com.zk.abstractFactory.AdidasFactory</className></config>
接下来同样的写一个Client类来试着运行看看效果。
public class Client { public static void main(String[] args) { try{ LabourFactory lFactory; Shoes shoes; Clothes clothes; lFactory = (LabourFactory) XMLUtil.getBean(); shoes = lFactory.produceShoes(); clothes = lFactory.produceClothes(); shoes.wear(); clothes.wear(); }catch (Exception e) { System.out.println(e.getMessage()); } }}
运行结果如图:
程序再次正确运行啦
总结:工厂模式与抽象工厂模式都属于创建型模式,在工厂模式中弥补了简单工厂模式的缺陷(不符合开闭原则),而在抽象工厂模式中弥补了工厂模式的不足(一个工厂只能生产一种产品)。
嘻嘻最后放一张萌猫壁纸
- 工厂模式与抽象工厂
- 工厂模式与抽象工厂模式
- 工厂模式与抽象工厂模式
- c#工厂模式与抽象工厂模式
- 简单工厂模式 与 抽象工厂模式
- c#工厂模式与抽象工厂模式
- 工厂方法模式与抽象工厂模式
- c#工厂模式与抽象工厂模式
- 工厂方法模式与抽象工厂模式
- 工厂模式与抽象工厂模式
- 工厂方法模式与抽象工厂模式
- 工厂方法模式与抽象工厂模式
- 工厂方法模式与抽象工厂模式
- 工厂方法模式与抽象工厂模式
- 工厂方法模式与抽象工厂模式
- 工厂方法模式与抽象工厂模式
- 工厂方法模式与抽象工厂模式
- 工厂方法模式与抽象工厂模式
- MySQL--多表更新
- Matlab中对字符串的处理(转 备查)
- Java内存区域的划分
- 独家 | 社交媒体假新闻检测方法及发展方向(附数据集)
- 啊啊啊
- 工厂模式与抽象工厂模式
- 【C#与.NET程序设计】(2)- C#基本数据类型及控制结构
- 使用小米手机开发调试遇到无法安装APK的问题
- 页面模板——freemaker对比velocity、jsp的模板
- Android 调用系统分享(不使用第三方),指定QQ、微信等
- Java的OutOfMemoryError和StackOverflowError
- 一个程序员6年的浏览器收藏夹
- 自步学习之SPLD
- 富士通半导体和安森美半导体宣布加强战略合作关系