工厂设计模式分为三种:
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表示完整的包.类名称
在使用时工厂就会根据配置文件所提供的实现类反射出对象,而我们如果要切换实现类,只需要修改一下配置文件即可,但不需要修改源代码。