设计模式背后的思想:
面向接口编程而不是面向实现编程
优先使用组合而不是继承
发现变化并且封装变化—把有变化的抽象出来,抽象出来更加灵活
简单工厂模式(Simple Factory Pattern)
简单工厂模式:定义一个Factory类,Factory只有一个create方法,可以根据参数的不同返回不同类的实例,被创建的实例通常有共同的父类。
简单工厂模式:只需要一个Factory类。
简单工厂模式:又称为静态工厂模式(Static Factory Pattern),Factory类为静态类或包含静态方法。
简单工厂模式:不属于23种GOF设计模式,但在软件开发中应用比较频繁。
简单工厂模式:实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类实例。
简单工厂模式结构图
简单工厂所包含的类:
Product: 抽象产品类,将具体产品类公共的代码进行抽象和提取后封装在一个抽象产品类中。
ConcreteProduct:具体产品类,将需要创建的各种不同产品对象的相关代码封装到具体产品类中。
Factory:工厂类,提供一个工厂类用于创建各种产品,在工厂类中提供一个创建产品的工厂方法,该方法可以根据所传入参数的不同创建不同的具体产品对象。
Client:客户端类,只需调用工厂类的工厂方法并传入相应的参数即可得到一个产品对象。
代码如下:
Factory:
public class Factory {
//静态工厂方法
public static Product createProduct(String type) {
Product product = null;
if (type.equals("ConcreteProductA")) {
product = new ConcreteProductA();
return product;
} else if (type.equals("ConcreteProductB")) {
product = new ConcreteProductB();
return product;
} // 等等其他的具体实例
return product;
}
}
Product:
public abstract class Product {
public abstract void disPlay();
// 等等具体类中公共的方法
}
ConcreteProduct:
public class ConcreteProductA extends Product {
@Override
public void disPlay() {
// 该类具体的逻辑业务,在这里只显示该类名称
System.out.println("ConcreteProductA");
}
}
public class ConcreteProductB extends Product {
@Override
public void disPlay() {
// 该类具体的逻辑业务,在这里只显示该类名称
System.out.println("ConcreteProductB");
}
}
Cilent:
public class Client {
public static void main(String[] args) {
String type = "ConcreteProductA";
Product product = Factory.createProduct(type);
product.disPlay();
}
}
方案改进:
由于每次创建一个实例要传入一个String类型的type,但每更换一个对象时就要修改客户端代码中type的值,客户端要重新编译,对于客户而言,违反了开闭原则(对扩展开发对修改关闭),那么有没有一种不修改客户端代码的前提下更换具体产品的对象呢?肯定是有的
可以将静态工厂方法的参数储存在XML或者properties格式的配置文件中,如config.xml代码如下:
config.xml
<?xml version = "1.0">
<config>
<Type>ConcreteProductA</Type>
</config>
// 注明: 如果ConceteProductA有package则要写上包名加上一个点 package.ConcreteProductA
client
public class Client {
public static void main(String[] args) {
String type = XMLUtil.getChartType(); // 通过配置文件得到参数
Product product = Factory.createProduct(type); // 创建产品对象
product.disPlay();
}
}
XMLUtil
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 getChartType() {
try {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document;
document = documentBuilder.parse(new File("config.xml"));
NodeList nodeList = document.getElementsByTagName("Type");
Node classNode = nodeList.item(0).getFirstChild();
String chartType = classNode.getNodeValue();
return chartType;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
简单工厂模式优点:
- 实现了创建对象和使用对象相分离
- Client无需知道所创建的ConcreteProduct类名,只需要知道ConcreteProduct所对应的参数
简单工厂模式的缺点:
- 由于工厂类集中了所有产品的创建逻辑,职责过重。
- 系统扩展困难,一旦添加新的具体产品就不得不修改工厂逻辑(增加一个else if())
- 由于使用了静态工厂方法,造成工厂角色无法形成基于继承等级结构(静态属性和私有属性不能被继承)