工厂模式
描述
目标:定义一个创建对象的工厂类,由工厂封装实例化对象的行为(代码)。使用对象时,只需找工厂拿即可,不用关心创建对象的细节。
简单工厂模式
原理
把产品统一交由工厂来创建管理,客户端要什么产品,就去找工厂创建。
结构
- 具体工厂:SimpleFactory
- 抽象产品:Duck
- 具体产品:BlackDuck,YellowDuck
实现
interface Duck {
void say();
}
class BlackDuck implements Duck {
@Override
public void say() {
System.out.println("black Duck");
}
}
class YellowDuck implements Duck {
@Override
public void say() {
System.out.println("yellow Duck");
}
}
class SimpleFactory {
// 服务端 鸭子的创建都交由工厂来处理,不暴露给客户端
// public static Dark createDark(String type) //静态工厂模式
public Duck createDuck(String type) {
if ("black".equals(type)) {
return new BlackDuck();
} else if ("yellow".equals(type)) {
return new YellowDuck();
}
return null;
}
}
class Test {
public static void main(String[] args) {
// 客户端调用
new SimpleFactory().createDuck("yellow").say();
}
}
好处
- 把创建对象交由服务端,对客户端隐藏(降低客户端修改的可能性)。客户端不用关心对象如何创建。
- 业务代码与对象创建耦合降低
坏处
- 有新需要修改工厂代码,违反开闭原则,工厂代码耦合度较高、
- 随着规模的扩大,简单工厂类会越来越庞大,可维护性不是特别好。
工厂方法模式
原理
为每类产品,创建一个各自的产品工厂,客户端需要哪种产品,就去找这种产品的工厂创建。
结构
- 抽象工厂:DuckFactory
- 具体工厂:RedDuckFactory,BlackDuckFactory
- 抽象产品:Duck
- 具体产品:BlackDuck,RedDuck
实现
interface Duck {
void say();
}
class BlackDuck implements Duck {
@Override
public void say() {
System.out.println("Duck black");
}
}
class RedDuck implements Duck{
@Override
public void say() {
System.out.println("Duck red");
}
}
interface DuckFactory {
Duck createInstance();
}
class RedDuckFactory implements DuckFactory {
@Override
public Duck createInstance() {
return new RedDuck();
}
}
class BlackDuckFactory implements DuckFactory {
@Override
public Duck createInstance() {
return new BlackDuck();
}
}
public class Test {
public static void main(String[] args) {
// 客户端
// 想要哪个厂地的鸭子,就去哪个工厂创建
Duck red = new RedDuckFactory().createInstance();
red.say();
Duck red1 = new BlackDuckFactory().createInstance();
red1.say();
}
}
好处
- 遵守开闭原则
- 要对象,只需要对象工厂,不关心对象的具体创建过程。
坏处
- 每新增一种对象,就要创建一个对应的对象工厂,容易类膨胀,增加系统复杂度。
抽象工厂模式
- 简单工厂,方法工厂只考虑生产同级别产品。如:鸭子工厂,只生产鸭子。
- 抽象工厂考虑多等级产品的生产。如:家禽工厂,生产鸭子,还生产鸡,鹅等。
先提:
- 产品族: 同一个工厂所生产的不同等级的一组产品。
- 例如: 家禽工厂,鸭子属于统一级别,鸡属于统一级别。
而红色家禽工厂生产的鸭子,鸡 属于同一个产品族,黑色家禽工厂生产的鸭子,鸡 属于同一个产品族
原理:
- 为客户端类提供一个创建一组相关或相互依赖对象的接口。无需指定所需产品的具体类,就能得到同族多个等级的产品。
结构
- 抽象工厂:DuckFactory
- 具体工厂:RedDuckFactory,BlackDuckFactory
- 抽象产品:Duck
- 具体产品:BlackDuck,RedDuck
实现
public class Test {
public static void main(String[] args) {
// 要什么颜色的产品族,就去什么颜色的工厂
Factory factory = new RedFactory();
factory.createChicken().speak();
factory.createDuck().say();
factory = new BlackFactory();
factory.createChicken().speak();
factory.createDuck().say();
}
}
interface Duck {
void say();
}
class BlackDuck implements Duck {
@Override
public void say() {
System.out.println("black Duck");
}
}
class RedDuck implements Duck {
@Override
public void say() {
System.out.println("red Duck");
}
}
interface Chicken {
void speak();
}
class BlackChicken implements Chicken {
@Override
public void speak() {
System.out.println("black Chicken");
}
}
class RedChicken implements Chicken {
@Override
public void speak() {
System.out.println("red Chicken");
}
}
interface Factory {
Duck createDuck();
Chicken createChicken();
}
class BlackFactory implements Factory{
@Override
public Duck createDuck() {
return new BlackDuck();
}
@Override
public Chicken createChicken() {
return new BlackChicken();
}
}
class RedFactory implements Factory{
@Override
public Duck createDuck() {
return new RedDuck();
}
@Override
public Chicken createChicken() {
return new RedChicken();
}
}
优点
- 如果需要添加一个新的产品族,只需要添加一个对应的工厂即可。
- 当产品族中的对象设计成一起工作时,能保证客户端只能使用同一个产品族的对象。
缺点
- 如果需要添加一个新产品,所有的工厂都需要添加该新产品。
使用场景
- 每个工厂都要有一族中所有的产品,每次只使用其中的一族的产品。
- 如:输入法,切换皮肤时,所有的组件(log,背景,样式)都要切换掉。
应用扩展
简单工厂+配置文件
配置文件:
red:abstractfactory.sinmple.factory.RedDuck
black:abstractfactory.sinmple.factory.BlackDuck
实现:
public class Test {
public static void main(String[] args) {
Duck red = SimpleFactory.getInstance("red");
red.say();
Duck black = SimpleFactory.getInstance("black");
black.say();
}
}
interface Duck {
void say();
}
class BlackDuck implements Duck {
@Override
public void say() {
System.out.println("black Duck");
}
}
class RedDuck implements Duck {
@Override
public void say() {
System.out.println("red Duck");
}
}
class SimpleFactory {
private static Map<String, Duck> duckMap = new HashMap<>();
static {
// 读取配置文件
Properties properties = new Properties();
InputStream inputStream = SimpleFactory.class.getClassLoader().getResourceAsStream("bean.properties");
try {
properties.load(inputStream);
Set<Object> objects = properties.keySet();
for (Object item : objects) {
String key = (String)item;
String classPath = properties.getProperty(key);
Duck duck = null;
duck = (Duck) Class.forName(classPath).newInstance();
duckMap.put(key, duck);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static Duck getInstance(String name) {
return duckMap.get(name);
}
}
优点:遵守开闭原则,后期创建新的对象,创建后只需配置文件配置一下即可。
JDK中的工厂模式
Calendar.getInstance 简单工厂:
- 通过参数,决定创建哪个实例对象