工厂设计模式分为三种:
1、简单工厂设计模式(Simple Factory)
2、工厂设计模式(Factory Method)
3、抽象设计模式(Abstract Factory)
这三种工厂设计模式都属于创建型设计模式,都是将对象的实例化部分取出来,优化系统架构,增强系统的扩展性。
1、简单工厂模式:
又叫静态工厂,是工厂模式三中状态中结构最为简单的。主要有一个静态方法,用来接受参数,并根据参数来决定返回实现同一接口的不同类的实例
角色:
1、工厂类角色(SimpleFactory):根据逻辑不同,产生不同的产品ConcreteProduct;
2、抽象产品角色(Product):接口或抽象类,
3、具体产品角色(ConcreteProduct):工厂类创建的具体实例对象。
类图:
实现代码:
/**
* 产品接口
* @author zzj
*
*/
public interface IProduct {
void act();
}
/**
* 具体实现类
* 相当于ConcreteProductA
* @author zzj
*
*/
public class Washer implements IProduct {
public Washer(){
System.out.println("Washer is produced");
}
@Override
public void act() {
System.out.println("Wash the clothes!");
}
}
/**
* 具体实现类
* 相当于ConcreteProductB
* @author zzj
*
*/
public class AirCondition implements IProduct {
public AirCondition(){
System.out.println("AirCondition is produced");
}
@Override
public void act() {
System.out.println("Cool down!");
}
}
/**
* 生产工厂类
* @author zzj
*
*/
public class SimpleFactory {
public static IProduct createFactory(String productName) throws Exception{
if("washer".equals(productName)){
return new Washer();
}else if("airCondition".equals(productName)){
return new AirCondition();
}else{
throw new Exception();
}
}
}
/**
* 简单工厂客户端
* @author zzj
* 2017/6/3
*/
public class Client {
public static void main(String[] args){
try {
SimpleFactory.createFactory("washer");
SimpleFactory.createFactory("airCondition");
//冰箱
SimpleFactory.createFactory("Icebox");
} catch (Exception e) {
System.out.println("no product");
}
}
}
输出结果:
Washer is produced
AirCondition is produced
no product
优点:客户端可以免除直接创建产品对象的责任,而仅仅负责消费对象就可以了,这种做法就实现了对职责权利的分割,有利于优化结构
缺点:
1、每次想要增加一种新产品的时候,都必须修改SimpleFactory的原代码
2、如果产品过多,代码逻辑很复杂,整个系统都依赖SimpleFactory,一旦SimpleFactory出现问题,系统将不能工作。这点在工厂模式进行了改进。
2、工厂设计模式
工厂方法为工厂类定义了接口,用多态来削弱了工厂类的职能
又叫虚拟构造器模式或多态工厂,在工厂方法模式中,核心的工厂类不再负责所有的产品的创建,而是将具体创建的工作交给子类去做。该核心类成为一个抽象工厂角色,仅负责给出具体工厂子类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节。
角色:
1、抽象工厂角色(IFactory):抽象类或接口,
2、具体工厂角色(ConcreteFactory):和业务逻辑有关,创建具体的产品对象ConcreteProduct,
3、抽象产品角色(IProduct):抽象类或接口,
4、具体产品角色(ConcreteProduct):工厂类创建的具体实例对象。
类图:
实现代码:
/**
* 产品接口
* @author zzj
*
*/
public interface IProduct {
void act();
}
/**
* 具体实现类
* 相当于ConcreteProductA
* @author zzj
*
*/
public class Washer implements IProduct {
public Washer(){
System.out.println("Washer is produced");
}
@Override
public void act() {
System.out.println("Wash the clothes!");
}
}
/**
* 具体实现类
* 相当于ConcreteProductB
* @author zzj
*
*/
public class AirCondition implements IProduct {
public AirCondition(){
System.out.println("AirCondition is produced");
}
@Override
public void act() {
System.out.println("Cool down!");
}
}
/**
* 工厂接口
* @author zzj
*
*/
public interface IFactory {
IProduct create();
}
/**
* 具体实现类
* 相当于ConcreteFactoryA
* @author zzj
*
*/
public class WasherFactory implements IFactory {
@Override
public IProduct create() {
return new Washer();
}
}
/**
* 具体实现类
* 相当于ConcreteFactoryB
* @author zzj
*
*/
public class AirConditionFactory implements IFactory {
@Override
public IProduct create() {
return new AirCondition();
}
}
/**工厂方法客户端
* @author zzj
* 2017/6/3
*/
public class Client {
public static void main(String[] args){
IProduct product;
product = new WasherFactory().create();
product.act();
product = new AirConditionFactory().create();
product.act();
}
}
输出结果:
Washer is produced
Wash the clothes!
AirCondition is produced
Cool down!
在工厂方法模式中,核心的工厂类不再负责所有产品的创建,而是将具体创建工作交给子类去完成,这就允许系统在不修改工厂角色的情况下,创建新的产品。符合开闭原则
优点:每个产品都有自己对应的工厂类,互不干涉,增加或修改都不影响其他的产品
缺点:产品越多,需要创建的工厂类越多
3、抽象工厂设计模式
抽象工厂设计模式是对产品族而言的。给客户端提供一个接口,可以创建多个产品族中的产品对象。
适用条件:
1.系统中有多个产品族,而系统一次只可能消费其中一族产品
2.同属于同一个产品族的产品以其使用。
角色:
1、抽象工厂角色(IFactory):抽象类或接口,
2、具体工厂角色(ConcreteFactory):和业务逻辑有关,创建具体的产品对象ConcreteProduct,
3、抽象产品角色(IProduct):抽象类或接口,
4、具体产品角色(ConcreteProduct):工厂类创建的具体实例对象。
类图:
实现代码:
/**
* 相当于AbstractProductA
* @author zzj
*
*/
public interface Vehicle {
void run();
}
/**
* 相当于ProductA1
* @author zzj
*
*/
public class Car implements Vehicle {
public Car(){
System.out.println("car construct");
}
@Override
public void run() {
System.out.println("run car");
}
}
/**
* 相当于ProductA2
* @author zzj
*
*/
public class Plane implements Vehicle {
public Plane(){
System.out.println("plane construct");
}
@Override
public void run() {
System.out.println("run plane");
}
}
/**
* 相当于AbstractProductB
* @author zzj
*
*/
public interface Food {
void eat();
}
/**
* 相当于ProductB1
* @author zzj
*
*/
public class Apple implements Food {
public Apple(){
System.out.println("apple construct");
}
@Override
public void eat() {
System.out.println("eating apple");
}
}
/**
* 相当于ProductB2
* @author zzj
*
*/
public class Water implements Food {
public Water(){
System.out.println("water construct");
}
@Override
public void eat() {
System.out.println("drinking water");
}
}
/**
* 抽象工厂接口
* @author zzj
*
*/
public interface IFactory {
Vehicle createVehicle();
Food createFood();
}
/**
* 具体工厂类
* 相当于ConcreteFactory1
* 生产汽车和苹果
* @author zzj
*
*/
public class ConcreteFactory1 implements IFactory {
@Override
public Vehicle createVehicle() {
return new Car();
}
@Override
public Food createFood() {
return new Apple();
}
}
/**
* 具体工厂类
* 相当于ConcreteFactory2
* 生产飞机和水
* @author zzj
*
*/
public class ConcreteFactory2 implements IFactory {
@Override
public Vehicle createVehicle() {
return new Plane();
}
@Override
public Food createFood() {
return new Water();
}
}
/**
* 抽象工厂设计模式客户端
* @author zzj
* 2017/6/10
*/
public class Client {
public static void main(String[] args){
IFactory factory1 = new ConcreteFactory1();
factory1.createVehicle().run();
factory1.createFood().eat();
IFactory factory2 = new ConcreteFactory2();
factory2.createVehicle().run();
factory2.createFood().eat();
}
}
输出结果:
car construct
run car
apple construct
eating apple
plane construct
run plane
water construct
drinking water
优点:增加新的具体工厂和产品族很方便,无须修改已有系统,符合“开闭原则”
缺点:增加新的产品等级结构很复杂,需要修改抽象工厂和所有的具体工厂类。
三者区别:
简单工厂模式:
生成同一等级中的任何产品
创建工厂,工厂的作用就是创建接口
工厂类包含必要逻辑判断,根据客户端的选择动态实例化相关类
但是对于增加的新产品,需要修改工厂类。
违背开闭原则。
工厂方法:
生成统一等级结构中的固定产品
只有一个抽象产品类,可以派生出多个具体的产品类
每个具体工厂类创建一个具体产品类的实例
把简单工厂的内部逻辑判断移到客户端来实现,若要增加功能,修改客户端代码
新增加产品,增加对应的产品和具体工厂类即可
符合开封原则,保持封装对象创建过程的优点
抽象工厂:
用抽象工厂创建产品
生产不同产品族的全部产品
有多个抽象产品类,每个抽象产品类可以派生出多个具体的产品类
每个具体工厂类创建多个具体产品类的实例
简单工厂设计模式是工厂设计模式的一种特例。
抽象工厂和工厂设计模式的区别在于创建对象的复杂性上:
工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。
工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。
工厂类设计模式对新增加的类,修改比较多,所以采用反射的机制。
4、反射+简单工厂设计模式
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制
实现代码:
/**
* 抽象产品
* @author zzj
*
*/
public interface Fruit {
void eat();
}
/**
* 具体产品
* @author zzj
*
*/
public class Apple implements Fruit {
@Override
public void eat() {
System.out.println("eat apple");
}
}
/**
* 具体产品
* @author zzj
*
*/
public class Orange implements Fruit {
@Override
public void eat() {
System.out.println("eat orange");
}
}
/**
* 工厂类,创建实例
* @author zzj
*
*/
public class Factory {
public static Fruit getInstance(String className){
Fruit fruit = null;
try {
fruit = (Fruit) Class.forName(className).newInstance();
} catch (Exception e) {
System.out.println(e);
}
return fruit;
}
}
/**
* 工厂设计模式与反射结合
* @author zzj
* 2017/6/10
*/
public class Client {
public static void main(String[] args){
Fruit fruit = null;
fruit = Factory.getInstance("com.zzj.factory.reflectFactory.Apple");
if(fruit!=null){
fruit.eat();
}else{
System.out.println("no apple");
}
fruit = Factory.getInstance("com.zzj.factory.reflectFactory.Orange");
if(fruit!=null){
fruit.eat();
}else{
System.out.println("no orange");
}
fruit = Factory.getInstance("com.zzj.factory.reflectFactory.Banana");
if(fruit!=null){
fruit.eat();
}else{
System.out.println("no banana");
}
}
}
输出结果:
eat apple
eat orange
java.lang.ClassNotFoundException: com.zzj.factory.reflectFactory.Banana
no banana
优点:这样无论增加多少个子类,工厂类都不用做任何的修改。
可以要把实例的类写在配置文件中,在属性文件中使用apple和orange表示完整的包.类名称
在使用时工厂就会根据配置文件所提供的实现类反射出对象,而我们如果要切换实现类,只需要修改一下配置文件即可,但不需要修改源代码。