写在前面:设计模式,面试被提问率100%的知识点,体现你编程思路和面向对象理解,在各个框架中设计模式被应用的非常广泛。行了,吹不下去了,一句话,这很重要。。。
工厂模式:定义了一个用于创建对象的接口,让子类决定实例化哪个类,工厂方法使一个类的实例化延迟到其子类。
一般含有一下对象:
- 1、抽像工厂类
Factory
定义一个创建对象的接口 - 2、生产对应的产品的具体工厂类
ConcreteProductXFactory
具体工厂类只生产一种具体的产品 - 3、产品类
AbstractProduct
- 4、具体产品类
ConcreteProductX
具体产品类与具体工厂类一一对应
一、简单工厂模式
实例化对象的时候不再使用 new Object()形式,可以根据用户的选择条件来实例化相关的类。对于客户端(调用方)来说,去除了具体的类的依赖。只需要给出具体实例的描述给工厂,工厂就会自动返回具体的实例对象。
public interface SoftEngineer{
public void develop();
}
//后端研发
public class RD implements SoftEngineer{
public void develop(){
System.out.Println("开发后端代码!");
}
}
//前端研发
public class FE implements SoftEngineer{
public void develop(){
System.out.Println("开发前端代码!");
}
}
//测试
public class QA implements SoftEngineer{
public void develop(){
System.out.Println("测试!");
}
}
//工厂类
public class EngineerFactory(){
public static SoftEngineer getEngineer(String name){
switch(name){
case:"RD"
return new RD();
case:"FE"
return new FE();
case:"QA"
return new QA();
}
}
}
优点:我们可以对创建的对象进行一些 “加工” ,而且客户端并不知道,因为工厂隐藏了这些细节。如果,没有工厂的话,那我们是不是就得自己在客户端上写这些代码,这就好比本来可以在工厂里生产的东西,拿来自己手工制作,不仅麻烦以后还不好维护。
缺点:如果需要在方法里写很多与对象创建有关的业务代码,而且需要的创建的对象还不少的话,我们要在这个简单工厂类里编写很多个方法,每个方法里都得写很多相应的业务代码,而每次增加子类或者删除子类对象的创建都需要打开这简单工厂类来进行修改。这会导致这个简单工厂类很庞大臃肿、耦合性高,而且增加、删除某个子类对象的创建都需要打开简单工厂类来进行修改代码也违反了开-闭原则。
应用实例
制定不同加密算法的密钥生成器
二、工厂模式
由于简单工厂模式以上缺点,引出工厂模式:
工厂方法模式是对简单工厂模式进一步的解耦,因为在工厂方法模式中是一个子类对应一个工厂类,而这些工厂类都实现于一个抽象接口。这相当于是把原本会因为业务代码而庞大的简单工厂类,拆分成了一个个的工厂类,这样代码就不会都耦合在同一个类里了。
//工厂接口
public interface Factory{
public SoftEngineer getSoftEngineer();
}
//后端研发
public class RDFactory implements Factory{
public SoftEngineer getSoftEngineer(){
return new RD();
};
}
//前端研发
public class FEFactory implements Factory{
public SoftEngineer getSoftEngineer(){
return new FE();
};
}
//测试
public class QAFactory implements Factory{
public SoftEngineer getSoftEngineer(){
return new QA();
};
}
//工厂类
public class Test(){
public static void main(String args[]){
// 使用反射机制实例化工厂对象,因为字符串是可以通过变量改变的
Factory rDFactory = (Factory)Class.forName("org.zero01.factory.RDFactory ").newInstance();
Factory fEFactory = (Factory)Class.forName("org.zero01.factory.FeFactory ").newInstance();
SoftEngineer engineer=rDFactory.getSoftEngineer();
SoftEngineer engineer=fEFactory.getSoftEngineer();
}
}
工厂模式中,要增加产品类时也要相应地增加工厂类,客户端的代码也增加了不少。工厂方法把简单工厂的内部逻辑判断转移到了客户端代码来进行。
你想要加功能,本来是改工厂类的,而现在是修改客户端。而且各个不同功能的实例对象的创建代码,也没有耦合在同一个工厂类里,这也是工厂方法模式对简单工厂模式解耦的一个体现。工厂方法模式克服了简单工厂会违背开-闭原则的缺点,又保持了封装对象创建过程的优点。
但工厂方法模式的缺点是每增加一个产品类,就需要增加一个对应的工厂类,增加了额外的开发量。
应用实例
JDBC使用不同数据库,需要先下载配置数据库的driver,再进行连接
三、抽象工厂模式
抽象工厂是可以生产多个产品的,工厂模式生产单一产品的。比如上述例子中,该工厂可生产软件工程师,假设他还可以生产建筑工程师,这就需要在工厂接口中添加获取建筑师实例的方法。
第一:
//工厂接口
public interface Factory{
public SoftEngineer getSoftEngineer();
public Architect getArchitect();
}
//建筑师接口
public interface Architect{
public void build();
}
//大楼建筑师
public class BuildingArchitect implements Architect {
public void build(){
System.out.println("建造大楼");
}
}
//桥梁建筑师
public class BridgeArchitect{
public void build(){
System.out.println("建造桥梁");
}
}
//大楼建筑师工厂类
public class BuildingArchitectFactory implements Factory{
public Architect getArchitect(){
return new BuildingArchitect ();
};
}
//桥梁建筑师工厂类
public class BridgeArchitectFactory implements Factory{
public BridgeArchitect getArchitect(){
return new BridgeArchitect ();
};
}
//调用方
public class Test(){
public static void main(String args[]){
Factory rDFactory=new RDFactory();
SoftNegineer rd=rDFactory.getEngineer();
rd.develop();
Factory buildingFactory=new BuildingArchitectFactory();
Factory bridgeFactory=new BridgeArchitectFactory ;
Architect buildingArc= buildingFactory.getArchitect();
Architect bridgeArc= bridgeFactory.getArchitect();
buildingArc.build();
bridgeArc.build();
}
}
优点:与工厂类相比,客户端不需要知道生产具体产品的工厂;客户端更换产品对象时,改动较少(只需要改动具体工厂类即可);增加具体的产品很方便,不需要修改已有的系统。
缺点:开闭原则的倾斜性(增加新的抽象产品类,需要修改整个工厂类极其子类,改动量巨大;增加新的工厂或具体产品,改动比较少)
适用场景
出现多个产品系列的场景,并且客户端并不关心产品创建逻辑。
应用实例
在很多软件系统中需要更换界面主题,要求界面中的按钮、文本框、背景色等一起发生改变时,可以使用抽象工厂模式进行设计。