一般情况下,我们使用new来创建对象,这种调用者和创建者是同一个,耦合度高,另外有些对象很复杂,只使用new很难满足要求。
工厂模式,属于创建型设计模式,生产的对象叫产品,生产产品的场所叫工厂。使用工厂模式不会向客户端暴露创建逻辑,而且可以进行复杂的初始化操作,并将创建工作延迟到子类。工厂模式实现了对象的创建过程统一管理。
工厂模式分为简单(静态)工厂、普通工厂、抽象工厂三类。
1. 简单(静态)工厂
简单工厂,就是使用具体的工厂来生产多种产品。通常情况下客户端只需要传入要创建的产品的种类,就可以得到需要的产品。
优点:隐藏了创建对象的细节,实现了调用者与创建者的解耦。
缺点:违法开闭原则,扩展产品时需要修改工厂的方法。
产品(语言)
public interface Language {
void displayname();
}
public class Java implements Language{
@Override
public void displayname() {
System.out.println("I am Java");
}
}
public class C implements Language{
@Override
public void displayname() {
System.out.println("I am C");
}
}
public class Python implements Language{
@Override
public void displayname() {
System.out.println("I am Python");
}
}
工厂
public class LanguageFactory {
//根据传入的语言类型创建相应的语言类
public Language getLanguage(String Name){
if("Java".equals(Name)){
return new Java();
}else if("C".equals(Name)){
return new C();
}else if("Python".equals(Name)){
return new Python();
}
return null;
}
}
调用
public class LanguageDemo {
public static void main(String[] args) {
LanguageFactory lf = new LanguageFactory();
Language java = lf.getLanguage("Java");
java.displayname();
Language c = lf.getLanguage("C");
c.displayname();
Language python = lf.getLanguage("Python");
python.displayname();
}
}
输出
I am Java
I am C
I am Python
当然上述的工厂也可以使用反射来解决每次新增加一种产品就需要修改相应的创建方法的缺点。
使用反射的工厂
public class ReflectLanguageFactory {
public static Object getClass(Class<? extends Language> clazz){
Object object = null;
try {
object = Class.forName(clazz.getName()).newInstance();
} catch (InstantiationException | IllegalAccessException
| ClassNotFoundException e) {
e.printStackTrace();
}
return object;
}
}
调用
public class InflectLanguageDemo {
public static void main(String[] args) {
Java java = (Java) ReflectLanguageFactory.getClass(Java.class);
java.displayname();
C c = (C) ReflectLanguageFactory.getClass(C.class);
c.displayname();
Python python = (Python) ReflectLanguageFactory.getClass(Python.class);
python.displayname();
}
}
输出
I am Java
I am C
I am Python
但是又和new对象有什么区别?
还有一种做法是在工厂类中每一个产品都由单独的一个方法创建,这种是多方法工厂模式。
2.普通工厂
普通工厂与简单工厂的区别是:它拥有抽象工厂层和多个具体子类工厂层;
普通工厂与抽象工厂的区别是:普通工厂针对的是同一系列的产品,而抽象工厂针对的是不同系列的产品,也可以理解成抽象工厂是生产工厂的工厂。
产品
public interface Language {
void displayname();
}
public class Java implements Language{
@Override
public void displayname() {
System.out.println("I am Java");
}
}
public class C implements Language{
@Override
public void displayname() {
System.out.println("I am C");
}
}
public class Python implements Language{
@Override
public void displayname() {
System.out.println("I am Python");
}
}
工厂
public abstract class LanguageFactory {
public abstract Language createLanguage();
}
public class JavaFactory extends LanguageFactory{
@Override
public Language createLanguage() {
return new Java();
}
}
public class CFactory extends LanguageFactory{
@Override
public Language createLanguage() {
return new C();
}
}
public class PythonFactory extends LanguageFactory{
@Override
public Language createLanguage() {
return new Python();
}
}
调用
public class LanguageDemo {
public static void main(String[] args) {
LanguageFactory jf = new JavaFactory();
Language java = jf.createLanguage();
java.displayname();
LanguageFactory cf = new CFactory();
Language c = cf.createLanguage();
c.displayname();
LanguageFactory pf = new PythonFactory();
Language python = pf.createLanguage();
python.displayname();
}
}
输出
I am Java
I am C
I am Python
优点:遵循了开闭原则
缺点:增加了类组织的复杂度
3.抽象工厂
抽象工厂可以看作是创建工厂的工厂,它可以将一系列相关的产品系列组合在一起。
下面我们以码农和律师的穿衣风格来讲述抽象工厂。假设码农和律师都需要要衣服和鞋子:
产品(衣服)
public interface Clothes {
void info();
}
public class TShirt implements Clothes{
@Override
public void info() {
System.out.println("我是T恤");
}
}
public class Suit implements Clothes{
@Override
public void info() {
System.out.println("我是西服");
}
}
产品(鞋)
public interface Shoes {
void info();
}
public class Slipper implements Shoes{
@Override
public void info() {
System.out.println("我是拖鞋");
}
}
public class LeatherShoes implements Shoes{
@Override
public void info() {
System.out.println("我是皮鞋");
}
}
工厂
public interface StyleFactory {
Clothes createClothes();
Shoes CreateShoes();
}
//码农风格工厂
public class ProgrammerStyleFactory implements StyleFactory{
@Override
public Clothes createClothes() {
return new TShirt();
}
@Override
public Shoes CreateShoes() {
return new Slipper();
}
}
//律师风格工厂
public class LawyerStyleFactory implements StyleFactory{
@Override
public Clothes createClothes() {
return new Suit();
}
@Override
public Shoes CreateShoes() {
return new LeatherShoes();
}
}
调用
public class StyleDemo {
public static void main(String[] args) {
System.out.println("放荡不羁的码农风格:");
StyleFactory psf = new ProgrammerStyleFactory();
Clothes clothes = psf.createClothes();
clothes.info();
Shoes shoes = psf.CreateShoes();
shoes.info();
System.out.println("严肃端正的律师风格:");
StyleFactory lsf = new LawyerStyleFactory();
Clothes clothes2 = lsf.createClothes();
clothes2.info();
Shoes shoes2 = lsf.CreateShoes();
shoes2.info();
}
}
输出
放荡不羁的码农风格:
我是T恤
我是拖鞋
严肃端正的律师风格:
我是西服
我是皮鞋
优点:支持不同产品类型的组合。
缺点:违背开闭原则,每次增加一个新的产品,所有工厂都需增加一个方法。