工厂模式简介
工厂模式(Factory Pattern)是Java中最常用的设计模式之一。它提供了一种创建对象的最佳方式。在工厂模式中,在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
主要解决:接口选择问题。
何时使用:明确地计划不同条件下创建不同实例时。
如何解决:让其子类实现工厂接口,返回的也是一个抽象的产品。
关键代码:创建过程在其子类进行。
应用实例:想要一辆汽车,可直接从工厂里面提货,不用管这辆车是怎么做出来的,也不用管汽车里的具体实现。
优点:一个调用者想创建一个对象,只需知道其名称即可。扩展性高,若想增加一个产品,只需扩展一个工厂类就可以。屏蔽产品的具体实现,调用者只关心产品接口。
缺点:每次增加一个产品时,都需增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程序上增加了系统的复杂度,同时也增加了系统具体类的依赖。
使用场景:日志记录器,记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。
数据库访问,当用户不知道系统最后采用哪一类数据库,以及数据库可能有变化时。
注:作为一种创建型设计模式,在任何需要生成复杂对象的地方,都可使用工厂模式。复杂对象适合使用工厂模式,而简单对象,特别是只需通过new就可完成创建的对象,无需使用工厂模式。若使用工厂模式,就需引入一个工厂类,会增加系统复杂度。
例
创建接口
public interface Person {
void eat();
}
创建接口实现类
Chinese类
public class Chinese implements Person {
public void eat() {
System.out.println("吃水饺。。。");
}
}
American类
public class American implements Person {
public void eat() {
System.out.println("Eat KFC。。。");
}
}
British类
public class British implements Person {
public void eat() {
System.out.println("Eat Bread。。。");
}
}
创建工厂,生成基于给定信息的实体类对象
public class PersonFactory {
public Person getPerson(String person) {
if (person == null) {
return null;
}
if (person.equalsIgnoreCase("Chinese")) {
return new Chinese();
} else if (person.equalsIgnoreCase("American")) {
return new American();
} else if (person.equalsIgnoreCase("British")) {
return new British();
}
return null;
}
}
使用工厂,通过传递类型信息来获取实体类对象
public class FactoryPatternDemo {
public static void main(String[] args) {
//新建工厂对象
PersonFactory pFactory = new PersonFactory();
//通过工厂获取chinese对象
Person chinese = pFactory.getPerson("Chinese");
chinese.eat();
//通过工厂获取american对象
Person american = pFactory.getPerson("American");
american.eat();
//公共工厂获取british对象
Person british = pFactory.getPerson("British");
british.eat();
}
}
输出结果为
吃水饺。。。
eat KFC。。。
eat Bread。。。
抽象工厂模式简介
抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂,该超级工厂又称为其他工厂的工厂。
在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。
意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
主要解决:接口选择问题。
何时使用:系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
如何解决:在一个产品族里面,定义多个产品。
关键代码:在一个工厂里聚合多个同类产品。
优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的Creator里加代码,又要在具体的里面加代码。
注:产品族难扩展,产品等级易扩展。
抽象工厂说白了就是在工厂里面获取工厂。
实例场景:将一所大学比作一个超级工厂,学校里的各个系比作从超级工厂获取的子工厂,每个系下面的各个班级比作从子工厂获取的各个对象(各个子工厂中的各个对象须有共性)。
例
定义Information接口(学院)
public interface Information {
void study();
}
定义Software类(专业)
public class Software implements Information {
public void study() {
System.out.println("Study Software。。。");
}
}
定义Network类(专业)
public class Network implements Information {
public void study() {
System.out.println("Study Network。。。");
}
}
定义Computer类(专业)
public class Computer implements Information {
public void study() {
System.out.println("Study Computer。。。");
}
}
定义Physical接口(学院)
public interface Physical {
void train();
}
定义Athletics类(专业)
public class Athletics implements Physical {
public void train() {
System.out.println("Train Athletics。。。");
}
}
定义Basketball类(专业)
public class Basketball implements Physical {
public void train() {
System.out.println("Train Bastetball。。。");
}
}
定义Football类(专业)
public class Football implements Physical {
public void train() {
System.out.println("Train Football。。。");
}
}
为Information和Phyfical对象创建抽象类来获取工厂
public abstract class AbstractFactory {
public abstract Information getInformation(String information);
public abstract Physical getPhysical(String physical);
}
创建扩展了AbstractFactory的工厂类,基于给定信息生成实体类对象
public class InformationFactory extends AbstractFactory {
public Information getInformation(String information) {
if (information == null) {
return null;
}
if (information.equalsIgnoreCase("Software")) {
return new Software();
} else if (information.equalsIgnoreCase("Network")) {
return new Network();
} else if (information.equalsIgnoreCase("Computer")) {
return new Computer();
}
return null;
}
public Physical getPhysical(String physical) {
return null;
}
}
public class PhysicalFactory extends AbstractFactory {
public Information getInformation(String information) {
return null;
}
public Physical getPhysical(String physical) {
if (physical == null) {
return null;
}
if (physical.equalsIgnoreCase("Athletics")) {
return new Athletics();
} else if (physical.equalsIgnoreCase("Basketball")) {
return new Basketball();
} else if (physical.equalsIgnoreCase("Football")) {
return new Football();
}
return null;
}
}
创建一个工厂创造器/生成器类,通过传递Information或Physical信息来获取工厂
public class FactoryProducer {
public static AbstractFactory getFactory(String factory) {
if (factory.equalsIgnoreCase("Information")) {
return new InformationFactory();
} else if (factory.equalsIgnoreCase("physical")) {
return new PhysicalFactory();
}
return null;
}
}
使用FactoryProducer获取AbstractFactory,通过传递类信息来获取实体类对象
public class AbstractFactoryPatternDemo {
public static void main(String[] args) {
//获取信息学院(工厂)
AbstractFactory informationFactory = FactoryProducer.getFactory("Information");
//获取软件专业(对象)
Information software = informationFactory.getInformation("Software");
software.study();
//获取网络专业(对象)
Information network = informationFactory.getInformation("Network");
network.study();
//获取计算机专业(对象)
Information computer = informationFactory.getInformation("Computer");
computer.study();
//获取体育学院(工厂)
AbstractFactory physicalFactory = FactoryProducer.getFactory("Physical");
//获取田径专业(对象)
Physical athletics = physicalFactory.getPhysical("Athletics");
athletics.train();
//获取篮球专业(对象)
Physical basketball = physicalFactory.getPhysical("Basketball");
basketball.train();
//获取足球专业(对象)
Physical football = physicalFactory.getPhysical("Football");
football.train();
}
}
输出结果为
Study Software。。。
Study Network。。。
Study Computer。。。
Train Athletics。。。
Train Basketball。。。
Train Football。。。