个人简介:荡不羁,一生所爱。Java耕耘者(微信公众号ID:Java耕耘者),欢迎关注。可获得2000G详细的2020面试题的资料
JAVA有23种设计模式,工厂方法模式和抽象工厂方法都是是其中创建型模式中的一种,23种设计模式如下图所示:
这次主要讲工厂方法模式和抽象工厂方法.
关于工厂方法,一般会提到简单工厂、工厂方法、抽象工厂这三个,GOF在《设计模式》一书中工厂模式分为两类:工厂方法模式(Factory Method)与抽象工厂模式(Abstract Factory)。将简单工厂模式(Simple Factory)看为工厂方法模式的一种特例,两者归为一类。
一、定义
-
简单工厂模式**(Simple Factory)**:专门定义一个类用来负责创建其他类的实例,被创建的实例通常都具有共同的父类.
-
工厂方法模式**(Factory Method)**:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类
-
抽象工厂模式**(Abstract Factory)**:提供一个创建一系列相关或者相互依赖对象的接口,而无需指定他们具体的类.
二、区别
工厂方法模式:
一个抽象产品类,可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类只能创建一个具体产品类的实例。
抽象工厂模式:
多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类可以创建多个具体产品类的实例。
区别:
工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。
工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。
三、代码实战说明
1、简单工厂模式
Store.java
public class Store {
public static void main(String[] args) {
//得到产品对象
Frute a=Factory.getFrute("apple");
if(a!=null)
System.out.println(a.tell());
//得到产品对象
Frute b=Factory.getFrute("banana");
if(a!=null)
System.out.println(a.tell());
}
} /
/工厂类
Factory.javapublic class Factory{
//只负责产生对象
public static Frute getFrute(String name){
if(name.equals("apple")){
return new Apple();
}
else if(name.equals("banana")){
return new Banana(); }
return null;
}
}
Frute.javapublic interface Frute{
public String tell(); }
//苹果类
Apple.javapub
lic class Apple implements Frute{
public String tell(){
return "我是苹果";
}
}
//香蕉类
Banana.javapublic class Banana implements Frute{
public String tell(){
return "我是香蕉";
}
}
优点:简单工厂模式能够根据外界给定的信息,决定究竟应该创建哪个具体类的对象。明确区分了各自的职责和权力,有利于整个软件体系结构的优化。
缺点:很明显工厂类集中了所有实例的创建逻辑,容易违反GRASPR的高内聚的责任分配原则,比如增加一个Grape类,不需要修改其他产品类,如Apple和banana,貌似符合OCP原则,但实际上还是需要对工厂类进行修改,所以简单工厂模式不符合OCP原则。
2、工厂模式
//创建一个接口
Shape.javapublic interface Shape {
oid draw();
}
//创建实现接口的实体类。
Rectangle.javapublic class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}
Square.javapublic class Square implements Shape {
@Override
public void draw() {
System.out.println("Inside Square::draw() method.");
}
}
Circle.javapublic class Circle implements Shape {
@Override
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}
//创建一个工厂,生成基于给定信息的实体类的对象
ShapeFactory.java
public class ShapeFactory {
//使用 getShape 方法获取形状类型的对象
public Shape getShape(String shapeType){
if(shapeType == null){
return null;
}
if(shapeType.equalsIgnoreCase("CIRCLE")){
return new Circle();
}
else if(shapeType.equalsIgnoreCase("RECTANGLE")){
return new Rectangle();
}
else if(shapeType.equalsIgnoreCase("SQUARE")){
return new Square();
}
return null;
}}
//使用该工厂,通过传递类型信息来获取实体类的对象。
FactoryPatternDemo.javapublic class FactoryPatternDemo {
public static void main(String[] args) {
ShapeFactory shapeFactory = new ShapeFactory();
//获取 Circle 的对象,并调用它的 draw 方法
Shape shape1 = shapeFactory.getShape("CIRCLE");
//调用 Circle 的 draw 方法
shape1.draw();
//获取 Rectangle 的对象,并调用它的 draw 方法
Shape shape2 = shapeFactory.getShape("RECTANGLE");
//调用 Rectangle 的 draw 方法
shape2.draw();
//获取 Square 的对象,并调用它的 draw 方法
Shape shape3 = shapeFactory.getShape("SQUARE");
//调用 Square 的 draw 方法
shape3.draw();
}
}
验证输出:
Inside Circle::draw() method.
Inside Rectangle::draw() method.
Inside Square::draw() method.
其实以上可以使用反射机制解决每次增加一次产品均需要增加一个实现工厂的缺点。
如下所示:
ShapeFactory.java(重写工厂)
public class ShapeFactory {
public static Object getClass(Class<?extends Shape> clazz) {
Object obj = null;
try
{
obj = Class.forName(clazz.getName()).newInstance();
}
catch (ClassNotFoundException e) {
e.printStackTrace();
}
catch (InstantiationException e) {
e.printStackTrace();
}
catch (IllegalAccessException e) {
e.printStackTrace();
}
return obj;
}
}
使
用的时候采用强制转换:
Rectangle rect = (Rectangle) ShapeFactory.getClass(Rectangle.class);
rect.draw();
Square square = (Square) ShapeFactory.getClass(Square.class);
square.draw();
3、抽象工厂模式
//发动机以及型号
Engine.javapublic interface Engine {
}
EngineA.javapublic class EngineA extends Engine{
public EngineA(){
System.out.println("制造-->EngineA");
}
}
EngineB.java public class EngineB extends Engine{
public EngineB(){
System.out.println("制造-->EngineB");
}
}
//空调以及型号
Aircondition.javapublic interface Aircondition {
}
AirconditionA.javapublic class AirconditionA extends Aircondition{
public AirconditionA(){
System.out.println("制造-->AirconditionA");
}
}
AirconditionB.javapublic class AirconditionB extends Aircondition{
public AirconditionB(){
System.out.println("制造-->AirconditionB");
}
}
//创建工厂类
//创建工厂的接口
AbstractFactory .javapublic interface AbstractFactory {
//制造发动机
public Engine createEngine();
//制造空调
public Aircondition createAircondition();
}
//为宝马320系列生产配件
FactoryBMW320.java public class FactoryBMW320 implements AbstractFactory{
@Override
public Engine createEngine() {
return new EngineA();
} @Override
public Aircondition createAircondition() {
return new AirconditionA();
}
}
//宝马523系列
FactoryBMW523.javapublic class FactoryBMW523 implements AbstractFactory {
@Override
public Engine createEngine() {
return new EngineB();
}
@Override
public Aircondition createAircondition() {
return new AirconditionB();
}
}
客户:public class Customer {
public static void main(String[] args){
//生产宝马320系列配件
FactoryBMW320 factoryBMW320 = new FactoryBMW320();
factoryBMW320.createEngine();
factoryBMW320.createAircondition();
//生产宝马523系列配件
FactoryBMW523 factoryBMW523 = new FactoryBMW523();
factoryBMW320.createEngine();
factoryBMW320.createAircondition();
}
}
优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。
注意事项:产品族难扩展,产品等级易扩展。
四、Spring中的应用
1、系统中使用的 JDBC:客户端通过数据操作工厂,利用jdbc接口,实现不同的数据库系统对象,从而根据具体的数据库类型(mysql、Oracledeng),使用不同jdbc
2、spring框架的Ioc容器beanFactory:生成并管理Bean
五、总结
无论是简单工厂模式,工厂方法模式,还是抽象工厂模式,他们都属于工厂模式,在形式和特点上也是极为相似的,他们的最终目的都是为了解耦。
(1)简单工厂模式是由一个具体的类去创建其他类的实例,父类是相同的,父类是具体的。
(2)工厂方法模式是有一个抽象的父类定义公共接口,子类负责生成具体的对象,这样做的目的是将类的实例化操作延迟到子类中完成。
(3)抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无须指定他们具体的类。它针对的是有多个产品的等级结构。而工厂方法模式针对的是一个产品的等级结构。
在使用工厂模式时,只需要关心降低耦合度的目的是否达到了。
干货分享最近将个人学习笔记整理成册,使用PDF分享主要包含了Java基础,数据结构,jvm,多线程等等,由于篇幅有限,以下只展示小部分面试题,
需要的朋友可以点一点领取:戳这里即可领取。。。
点关注,不迷路;持续更新Java相关技术及资讯!!!
今天的文章Java设计模式之工厂方法详解分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/20551.html