设计模式之工厂模式(二)之工厂方法模式
工厂方法模式
简单工厂模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了闭包原则,所以,从设计角度考虑,有一定的问题,如何解决?就用到工厂方法模式,创建一个工厂接口和创建多个工厂实现类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。
定义
工厂方法模式(Factory Method Pattern)同样属于类的创建型模式又被称为多态工厂模式(Polymorphic) 。工厂方法模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。
UML图
工厂方法模式中包含的角色及其相应的职责如下:
抽象工厂(Creator)角色:工厂方法模式的核心,任何工厂类都必须实现这个接口。
具体工厂( Concrete Creator)角色 : 具体工厂类是抽象工厂的一个实现,负责实例化
产品对象。
抽象(Product)产品角色:简单工厂模式所创建的所有对象的父类,注意,这里的父类可以是接口也可以是抽象类,它负责描述所有实例所共有的公共接口。
具体产品(Concrete Product)角色:简单工厂所创建的具体实例对象,这些具体的产品往往都拥有共同的父类。
后续补充UML类图。
基本思想
简单工厂模式使用一个类负责所有产品的创建,虽然使得客服端和服务端相互分离,使得客服端不用关心产品的具体创建过程,客户端唯一所要做的就是调用简单工厂的静态方法获得想要的产品即可。但是,简单工厂模式违背了严格意义上的“开放封闭原则”,这就使得一旦有一个新的产品增加就必须修改工厂类的源代码,从而将新的产品的创建逻辑加入简单工厂*客户端调用。
工厂方法法模式正是在简单工厂模式的基础上进一步抽象而来的 。由于工厂方法法模式的核心是抽象工厂角色,使用了面向对象的多态性,这就使得工厂方法法模式即保持了简单工厂模式的优点,又克服了简单工厂模式违背“开放封闭原则”的缺点。工厂方法法模式中核心工厂类不再提供所有的产品的创建工作,而是将具体的产品创建工作交给了子类去做。这时候的核心工厂类做什么呢?做标准!核心工厂类只需要负责制定
具体工厂需要实现的接口即可,至于具体的工作就留给了子类去创建了。
代码实现
1、创建一个抽象产品的接口
package com.zd.factoryt;
/**
* 创建一个抽象产品的接口
* @author Administrator
*
*/
public interface Shape {//产品的抽象接口
void draw();//生产产品的方法
}
2、创建实现抽象产品接口的具体产品实体类
package com.zd.factoryt;
public class Circle implements Shape{//实现抽象产品的接口
@Override
public void draw() {//获取产品
// TODO Auto-generated method stub
String str="我是一个圆形";
System.out.println(str);
}
}
package com.zd.factoryt;
public class Rectangle implements Shape{//实现抽象产品的接口
@Override
public void draw() {//获取产品
// TODO Auto-generated method stub
String str="我是一个长方形";
System.out.println(str);
}
}
package com.zd.factoryt;
public class Square implements Shape{//实现抽象产品的接口
@Override
public void draw() {//获取产品
// TODO Auto-generated method stub
String str="我是一个正方形";
System.out.println(str);
}
}
3、创建抽象工厂类接口
package com.zd.factoryt;
/**
* 创建一个抽象工厂的接口
* @author Administrator
*
*/
public interface ShapeFractory {//工厂的抽象接口
public Shape getShape();//工厂生产产品的方法
}
4、创建实现抽象工厂接口的具体工厂实体类
package com.zd.factoryt;
public class CircleFactory implements ShapeFractory{//实体工厂实现抽象工厂的接口
@Override
public Shape getShape() {//生产产品
// TODO Auto-generated method stub
return new Circle();
}
}
package com.zd.factoryt;
public class RectangleFactory implements ShapeFractory{//实体工厂实现抽象工厂的接口
@Override
public Shape getShape() {//生产产品
// TODO Auto-generated method stub
return new Rectangle();
}
}
package com.zd.factoryt;
public class SqureFactory implements ShapeFractory{//实体工厂实现抽象工厂的接口
@Override
public Shape getShape() {//生产产品
// TODO Auto-generated method stub
return new Square();
}
}
5、创建测试客户端类
package com.zd.factoryt;
/**
* 简单工厂模式测试客户端
* @author Administrator
*使用该工厂,通过传递类型信息来获取实体类的对象。
*/
public class TestFactory {
public static void main(String[] args) {
//获取Squre工厂
ShapeFractory squreFactory = new SqureFactory();
//获取 Squre 的对象,并调用它的 draw 方法
Shape squreShape = squreFactory.getShape();
//调用 Squre 的 draw 方法
squreShape.draw();
//获取Rectangle工厂
ShapeFractory rectangleFractory = new RectangleFactory();
//获取 Rectangle 的对象,并调用它的 draw 方法
Shape rectangleShape = rectangleFractory.getShape();
//调用 Rectangle 的 draw 方法
rectangleShape.draw();
//获取Circle工厂
ShapeFractory circleFractory = new CircleFactory();
//获取 Circle 的对象,并调用它的 draw 方法
Shape circleShape = circleFractory.getShape();
//调用 Circle 的 draw 方法
circleShape.draw();
}
}
6、测试效果
我是一个正方形
我是一个长方形
我是一个圆形
优缺点分析
优点:工厂方法类的核心是一个抽象工厂类,所有具体的工厂类都必须实现这个接口 。当系统扩展需要添加新的产品对象时,仅仅需要添加一个具体对象以及一个具体工厂对象 ,原有工厂对象不需要进行任何修改,也不需要修改客户端,这就很好的符合了“开放-封闭 ”原则。
缺点:使用工厂方法模式的时候,客户端需要决定实例化哪一个具体的工厂。也就是说工厂方法法模式把简单工厂模式的内部判断逻辑转移到了客户端代码。而且使用该模式需要增加额外的代码,这就导致工作量的增加。
实际应用
工厂方法模式解决的是同一系列的产品的创建问题,而且很好的满足了“开放封闭原则”,这需要创建同一系列产品的时候,使用工厂方法模式往往比使用简单工厂模式更好,尤其是对大型复杂的系统而言。
总结
工厂方法法模式解决了简单工厂模式的不足。在增加一个产品时,只需要一个具体的产品和创建产品的工厂类就可以,具有非常好的可维护性。但是也正因为如此,增加了代码量和工作量。不过瑕不掩瑜,因为增加的代码量不是很大的。后续补充UML类图。
首先感谢尚硅谷无偿提供的学习资料。写博客是为了帮助开发者学习使用技术,同时巩固自己所学技术。如果此篇博客有助于您的学习,那是我的荣幸!如果此篇博客有任何瑕疵,请多多指教!在此感谢您的学习和指教!