1.简单工厂模式
假如要设计一个类,根据用户输入参数的不同,产生不同的对象。
那么可以这样写:
public class Chart{
private String type;
public Chart{Object[][] data,String type){
this.type=type;
if(type.equalsIgnoreCase("aaa")){
// 第一种类型
}else if(type.equalsIgnoreCase("bbb")){
// 第二种类型
}else if(type.equalsIgnoreCase("ccc")){
// 第三种类型
}
}
public void display(){
if(this.type.equalsIgnoreCase("aaa")){
}else if (this.type.equalsIgnoreCase("bbb")){
}else if (this.type.equalsIgnoreCase("ccc")){
}
}
}
以上代码的缺点
1.过多的if else 使得代码很冗余
2.Chart类的职责过重,违反了单一原则
3.需要增加新的type时 需要更改代码,违反开闭原则
4.与使用者耦合度太高
5.每种type的chart都需要进行初始化,代码重复
这种情况下可以使用简单工厂模式:
简单工厂模式 又称 静态工厂模式
定义一个工厂类,根据参数的不同返回不同的 产品实例 ,产品实例有着共同的父类,即抽象的产品类。
要点:
传入一个正确的参数就可以获得一个对应的产品,而且无需知道创建细节。
修改后的代码 可以这么写:
abstract class Chart{
abstract void methodDiff();//每个type的chart的特有方法
public void methodSame(){ //所有type的chart的相同方法
}
}
class ChartA extends Chart{ //具体的chartA
public void methodDiff(){
}
}
class ChartB extends Chart{ //具体的chartB
public void methodDiff(){
}
}
class ChartFactory{
public static Chart getChart(String type){
Chart chart=null;
if(type.equalsIgnoreCase(“aaa”)){
chart=new ChartA();
}else if(type.equalsIgnoreCase("bbb")){
chart=new ChartB();
}
return chart;
}
}
// 客户端获取产品时 直接调用
Chart chart=ChartFactory.getChart("aaa");
总结
将对象的创建和使用分离
优点
1.对象的创建 和 使用分离
2.用户不需要知道创建的具体对象
3.可以引入配置文件,可以在不改变代码的情况下,添加或更换新的产品类
缺点
工厂类职责过重,产品类过多是会导致工厂类过于复杂。
违反开闭原则。
使用场景
产品类不多
客户端并不关心产品类如何创建
2.工厂方法模式
interface Product{
public void Method();
}
class ProductA implements Product{
public void Method(){
//产品A
}
}
class ProductB implements Product{
public void Method(){
//产品B
}
}
// 若A B产品初始化都需要 经历复杂的初始化
class ProductFactory{
public static Product getProduct(String type){
Product p=null;
if(type.equals("a")){
// 消耗大量资源的操作
p=new ProductA();
}else {
// 消耗大量资源的操作
p=new ProductB();
}
return p;
}
}
// 大量操作写到构造方法中就不合适
此时可以使用 工厂方法模式。
又名 虚拟构造器模式(Virtual Constructor Pattern)或多态工厂模式(Polymorphic Factory Pattern),定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。
interface Factory {
public Product getProduct();
}
class AFactory implements Factory {
public Product getProduct(){
// 消耗大量资源的操作
return new ProductA();//亦可以 不返回对象,直接在此调用Method()方法,即对使用者隐藏了工厂方法 即隐藏了具体的对象。也可以通过配置文件写入类名的方法,在此解析配置文件加载类名 然后反射产生对象
}
}
class BFactory implements Factory {
public Product getProduct(){ //亦可以弄几个多态方法,来生成产品
// 消耗大量资源的操作
return new ProductB();
}
}
工厂方法模式的总结:
优点
1. 有新产品时,只需添加新的产品类和工厂类,无需修改之前的代码 符合 开闭原则
2. 工厂类 和 产品类 都可以进行多态设计, 工厂可以自己确定创建哪个产品
3. 可以向调用者隐藏具体产品类,用户不知道到底创建了哪一个产品类。用户只关心对应的工厂,
缺点
- 需要引入抽象层,用户均使用抽象层的定义
- 在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类
3.抽象工厂模式
工厂方法模式 的情况下,每个工厂只生成一种产品。但是假如一个工厂要生成n种产品,而且有很多工厂时,那么 工厂方法模式 便不再合适。
此时可以使用抽象工厂方法。
若有 m个工厂,每个工厂都会生成相同的n种产品 。若按照一个工厂一种产品的想法,则需 m*n个工厂。
m个工厂,每个工厂称为一个产品族。
n种产品,称为n个产品等级。
抽象工厂方法的思路是:
AbstractFactory 定义生成这n种产品的方法,
| ProductA createProductA();
| ProductB createProductB();
| ProductC createProductC();
AbstractProduct 抽象的产品
ConcreteFactoryA extends AbstractFactory 具体工厂A
| ProductA createProductA();
| ProductB createProductB();
| ProductC createProductC();
ConcreteFactoryB extends AbstractFactory 具体工厂B
| ProductA createProductA();
| ProductB createProductB();
| ProductC createProductC();
即 定义m个工厂,均继承自抽象工厂,所以实现了构造各种产品的方法,产生了这n中产品等级的所有产品。这种写法,则需 m个工厂。
总结:
优点 :
- 抽象工厂模式隔离了具体类的生成,改变工厂类很容易。
- 保证客户端使用的是同一个产品族的对象,即同一个工厂的产品
- 增加新的产品族非常容易, 符合开闭原则
缺点:
增加新产品不方便,不符合开闭原则