设计模式是为解决生活中的问题而诞生的,也就是说我们可以通过生活中的问题来解释各种各样的模式,也是前人对代码开发经验的总结。
工厂模式分为简单工厂、工厂方法、抽象工厂。我们可以通过使用生活的例子来解释它们的作用
1、简单工厂可以看做一些小作坊模式,生产的产品由客户选择(简单工厂if、else或者case语句较多)
具体结构有:
工厂:实现产品的内部逻辑,由外界调用。
抽象产品:所有产品的共有方法,由产品实现。
产品:简单工厂模式的创建目标,所有被创建的对象都是某个具体类的实例。
工厂的产品
package des.factory;
public interface Milk {
/**
* 获取一个标准的产品
* @return
*/
String getName(String name);
}
抽象产品
package des.factory;
public class YiLi implements Milk{
@Override
public String getName(String name) {
return "YILI";
}
}
工厂
package des.factory.simple;
import des.factory.Milk;
import des.factory.YiLi;
public class SimpleFactory {
public Milk getName(String name){
if(name.equals("YiLi")){
return new YiLi();
}
return null;
}
}
简单工厂模式的优缺点及其适用环境
优点:
(1)工厂类中已经包含必要的逻辑判断,客户无需要创建产品类
(2)客户不需要知道具体的产品类,只需要知道具体的几个参数即可
(3)可以通过引入xml方式来产生和创建产品
缺点:
(1)工厂类中集齐了所有的逻辑判断职责过重,一旦出现异常,则会崩溃
(2)使用简单工厂模式会增加系统中类的个数(引入新的工厂类),增加系统的复杂度和理解难度
(3)系统扩展困难,一旦增加新产品不得不修改工厂逻辑,在产品类型较多时,可能造成逻辑过于复杂
适用环境:
(1)工厂类负责创建对的对象比较少,因为不会造成工厂方法中的业务逻辑过于复杂
(2)客户端只知道传入工厂类的参数,对如何创建对象不关心
2、工厂方法可以看做一条流水线进行生产,只能生产一个产品
具体的结构:
抽象工厂:声明抽象工厂的方法,用于生产一件产品。
具体工厂:实现产品的内部逻辑,由外界调用。
抽象产品:所有产品的共有方法,由产品实现。
产品:简单工厂模式的创建目标,所有被创建的对象都是某个具体类的实例。
代码在简单工厂的抽象产品,具体产品类的基础上添加抽象工厂、具体工厂
抽象工厂
package des.factory.func;
import des.factory.Milk;
public interface factory {
Milk getMilk();
}
具体工厂
package des.factory.func;
import des.factory.Milk;
import des.factory.YiLi;
public class YiLiFactory implements factory{
@Override
public Milk getMilk() {
return new YiLi();
}
}
工厂方法模式的优缺点及其适用环境
优点:
(1)更符合开-闭原则
新增一种产品时,只需要增加相应的具体产品类和相应的工厂子类即可
(2)符合单一职责原则
每个具体工厂类只负责创建对应的产品
(3)不使用静态工厂方法,可以形成基于继承的等级结构。
缺点:
(1)添加新产品时,除了增加新产品类外,还要提供与之对应的具体工厂类,系统类的个数将成对增加,在一定程度上增加了系统的复杂度;同时,有更多的类需要编译和运行,会给系统带来一些额外的开销;
(2)由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。
(3)虽然保证了工厂方法内的对修改关闭,但对于使用工厂方法的类,如果要更换另外一种产品,仍然需要修改实例化的具体工厂类;
(4)一个具体工厂只能创建一种具体产品
适用环境:
(1)当一个类不知道它所需要的对象的类时
在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可;
(2)当一个类希望通过其子类来指定创建对象时
在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏代换原则,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。
(3)将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定,可将具体工厂类的类名存储在配置文件或数据库中。
3抽象工厂可以看做一个大规模的工厂,标准化批量的生产多种商品
抽象工厂:声明抽象工厂的方法,用于生产多件产品。
具体工厂:实现产品的内部逻辑,由外界调用。
抽象产品:所有产品的共有方法,由产品实现。
产品:简单工厂模式的创建目标,所有被创建的对象都是某个具体类的实例。
在工厂方法的抽象产品,具体产品的基础上,增加抽象工厂,具体工厂
抽象工厂
package des.factory.abstrac;
import des.factory.Milk;
public abstract class AbstractFactory {
public abstract Milk getYiLi();
}
具体工厂
package des.factory.abstrac;
import des.factory.Milk;
import des.factory.YiLi;
public class MilkFactory extends AbstractFactory{
@Override
public Milk getYiLi() {
return new YiLi();
}
}
抽象工厂模式的优缺点及其适用环境
(1)具体产品在应用层代码隔离,无须关心创建细节
(2)将一系列的产品族统一到一起创建
(1)规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口
(2)增加了系统的抽象性和理解难度
适用环境
1、客户端(应用层)不依赖于产品类实例如何被创建、实现等细节
2、强调一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量重复的代码
3、提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现