设计模式——Factory工厂模式
工厂模式
实例化对象,用工厂方法代替new操作。定义一个创建对象的接口指向其实现的子类,让父类决定实例的生成方式,让子类决定实现的细节。这样有利于扩展。
工厂模式是Java中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。
应用实例: 1、JDBC中调用对数据库操作的API,而不必关系底层实现的是MySQL还是Oracle,只需要传入对应的类名。
优点: 1、一个调用者想创建一个对象,只要知道其名称就可以了。 2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。 3、屏蔽产品的具体实现,调用者只关心产品的接口。
缺点:每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。
Shape.java
定义一个接口,规范对象使用行为。
public interface Shape {
void draw();
}
两个实现类
实现相同的接口,细节实现不同的功能。
public class Square implements Shape {
@Override
public void draw() {
System.out.println("我是方形");
}
}
public class Circle implements Shape { @Override public void draw() { System.out.println("我是圆形"); } }
ShapeFactory.java
实现了三个方法分别对应不同的获取对象的方式,推荐使用第二和第三个方法,使用了反射机制,这样新增功能,比如三角形时,不用修改工厂类,而使用第一种方法需要修改。
public class ShapeFactory { //使用 getShape 方法获取形状类型的对象 public static Shape getShape(String shapeType) { if (shapeType == null) { return null; } if ("Circle".equals(shapeType)) { return new Circle(); } else if ("Square".equals(shapeType)) { return new Square(); } return null; } //根据类名获取 public static Shape getShapeByClassName(String className){ Shape shape=null; try { shape = (Shape) Class.forName(className).newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return shape; } //根据Class类型 获取 public static <T> T getShape(Class<? extends T> clazz) { T obj = null; try { obj = (T) Class.forName(clazz.getName()).newInstance(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return obj; } }
Test.java
测试,输出为:
我是圆形
我是方形
我是圆形
public class Test { public static void main(String[] args){ Shape shape1 = ShapeFactory.getShape("Circle"); shape1.draw(); Shape shape2 = ShapeFactory.getShapeByClassName("factory.shapepack.Square"); shape2.draw(); Shape shape3 = ShapeFactory.getShape(Circle.class); shape3.draw(); } }
抽象工厂模式
抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。
在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。
能够提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。在一个工厂里聚合多个同类产品。这里理解上有一定困难,打个比方:
工作了,为了参加一些聚会,肯定有两套或多套衣服吧,比如说有商务装(成套,一系列具体产品)、时尚装(成套,一系列具体产品),即一系列具体产品。假设一种情况,某一个衣柜(具体工厂)只能存放某一种这样的衣服(成套,一系列具体产品),每次拿这种成套的衣服时也自然要从这个衣柜中取出了。用 OO 的思想去理解,所有的衣柜(具体工厂)都是衣柜类的(抽象工厂)某一个,而每一件成套的衣服又包括具体的上衣(某一具体产品),裤子(某一具体产品),这些具体的上衣其实也都是上衣(抽象产品),具体的裤子也都是裤子(另一个抽象产品)。
示例代码,新增一个Color接口和Red和Blue两个实现类以及ColorFactory工厂类,类似于上面的Shape实现方式。
新增一个AbstractFactory抽象工厂类
public abstract class AbstractFactory { protected abstract Color getColor(String color); protected abstract Shape getShape(String shape) ; }
ColorFactory和ShapeFactory继承该抽象工厂类,如ColorFactory:
public class ColorFactory extends AbstractFactory { //简单起见这里不使用反射机制 public Color getColor (String colorType){ if (colorType == null) { return null; } if ("Red".equals(colorType)) { return new Red(); } else if ("Blue".equals(colorType)) { return new Blue(); } return null; } @Override //getShape不具体实现,让ShapeFactory去实现 protected Shape getShape(String shape) { return null; } }
新增一个工厂生成器类来获取对应的具体的工厂
FactoryProducer
public class FactoryProducer { public static AbstractFactory getFactory(String choice){ //这里简单起见不使用反射机制 if("Shape".equals(choice)){ return new ShapeFactory(); } else if("Color".equals(choice)){ return new ColorFactory(); } return null; } }
测试输出:
我是方形
填充红色
AbstractFactory shapeFactory = FactoryProducer.getFactory("Shape"); shapeFactory.getShape("Square").draw(); AbstractFactory colorFactory = FactoryProducer.getFactory("Color"); colorFactory.getColor("Red").fill();