一、简单工厂模式
1.概述
又叫做静态工厂方法模式,不属于23种GOF设计模式之一。是由一个工厂对象决定创建出哪一种产品类的实例。实质是由一个工厂类根据传入的参数,动态决定应该创建哪个产品类(这些产品类继承字一个父类或接口)的实例。
作用:将“类实例化的操作”与“使用对象的操作”分开,让使用者不用知道具体参数就可以实例化出所需要的“产品”类,从而避免了在客户端代码中显式指定,实现了解耦。
2.角色
工厂:负责实现创建所有实例的内部逻辑,并提供一个外界调用的方法,创建所需的产品对象。
抽象产品:负责描述产品的公共接口。
具体产品:描述生产的具体产品。
3.栗子
假设有一台饮料机(工厂),可以调出各种口味的饮料(抽象产品),有三个按钮(参数)对应这三种饮料(具体产品)。
1) 抽象产品
public interface Product {
void info();
}
2) 具体产品
class Tea implements Product {
@Override
public void info() {
System.out.println("This is tea");
}
}
class Milk implements Product {
@Override
public void info() {
System.out.println("This is Milk");
}
}
class Coffee implements Product {
@Override
public void info() {
System.out.println("This is Coffee");
}
}
3) 工厂
负责实现创建所有实例的内部逻辑,并提供一个外界调用的方法,创建所需的产品对象。
public class SimpleFactory {
public static Product getProduct(String type) {
if (type == null)
return null;
if (type.equalsIgnoreCase("tea")){
return new Tea();
} else if (type.equalsIgnoreCase("milk")) {
return new Milk();
} else if (type.equalsIgnoreCase("coffee")) {
return new Coffee();
}
return null;
}
}
4) 测试
public class FactoryTest {
public static void main(String[] args) {
// 创建具体的工厂
SimpleFactory factory = new SimpleFactory();
// 根据传入的参数生产不同的产品实例
Product p1 = SimpleFactory.getProduct("tea");
p1.info();
Product p2 = SimpleFactory.getProduct("milk");
p2.info();
Product p3 = SimpleFactory.getProduct("coffee");
p3.info();
}
}
4.总结
优点:将创建使用工作分开,不必关系类对象如何创建,实现了解耦
缺点:违背“开放-关闭原则”,一旦添加新产品就不得不修改工厂类的逻辑,这样就会造成工厂逻辑过于复杂
二、工厂方法模式
1.概述
又叫做工厂模式,通过定义工厂父类负责定义创建对象的公共接口,而子类则负责生成具体的对象。
作用:将类的实例化(具体产品的创建)延迟到工厂类的子类(具体工厂)中完成,即由子类来决定应该实例化(创建)哪一个类。
2.角色
抽象工厂:描述具体工厂的公共接口
具体工厂:描述具体工厂,创建产品的实例,供外界调用
抽象产品:负责描述产品的公共接口
具体产品:描述生产的具体产品
3.栗子
假设有各类的饮料机(抽象工厂),可以调出各种的饮料(抽象产品),但是一类饮料机(具体工厂),只能生产一种饮料(具体产品)。
1) 抽象产品
public interface Product {
void info();
}
2) 具体产品
class Tea implements Product {
@Override
public void info() {
System.out.println("This is Tea");
}
}
class Milk implements Product {
@Override
public void info() {
System.out.println("This is Milk");
}
}
class Coffee implements Product {
@Override
public void info() {
System.out.println("This is Coffee");
}
}
3) 抽象工厂
public interface Factory {
Product getProduct();
}
4) 具体工厂
class TeaFactory implements Factory {
@Override
public Product getProduct() {
return new Tea();
}
}
class MilkFactory implements Factory {
@Override
public Product getProduct() {
return new Milk();
}
}
class CoffeeFactory implements Factory {
@Override
public Product getProduct() {
return new Coffee();
}
}
5) 测试
public class FactoryTest {
public static void main(String[] args) {
TeaFactory teaFactory = new TeaFactory();
Product p1 = teaFactory.getProduct();
p1.info();
MilkFactory milkFactory = new MilkFactory();
Product p2 = milkFactory.getProduct();
p2.info();
CoffeeFactory coffeeFactory = new CoffeeFactory();
Product p3 = coffeeFactory.getProduct();
p3.info();
}
}
4.总结
优点:符合开-闭原则:新增一种产品时,只需要增加相应的具体产品类和相应的工厂子类即可;符合单一职责原则:每个具体工厂类只负责创建对应的产品
缺点:增加了系统的复杂度:类的个数将成对增加;增加系统的抽象性和理解难度;一个具体工厂只能创建一种具体产品
三、抽象工厂模式
1.概述
提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类;具体的工厂负责实现具体的产品实例。
抽象工厂模式与工厂方法模式的区别:抽象工厂中每个工厂可以创建多种类的产品;而工厂方法每个工厂只能创建一类。
2.角色
抽象工厂:描述具体工厂的公共接口
具体工厂:描述具体工厂,创建产品的实例,供外界调用
抽象产品族:描述抽象产品的公共接口
抽象产品:描述具体产品的公共接口
具体产品:具体产品
3.栗子
假设有各类的自动售卖机(抽象工厂),可以出售各类食品(抽象产品族)。有饮料、零食(抽象产品),比如常见的零食售卖机(具体工厂),出售茶水与面包(具体产品)。
1) 抽象产品族
public interface Product {
void info();
}
2) 抽象产品
interface Drink extends Product {
@Override
void info();
}
interface Snack extends Product {
@Override
void info();
}
3) 具体产品
class Tea implements Drink {
@Override
public void info() {
System.out.println("This is Tea");
}
}
class Bread implements Snack {
@Override
public void info() {
System.out.println("This is Bread");
}
}
4) 抽象工厂
public interface Factory {
Product getDrink();
Product getSnack();
}
5) 具体工厂
class DrinkFactory implements Factory {
@Override
public Product getDrink() {
return new Tea();
}
@Override
public Product getSnack() {
return null;
}
}
class SnackFactory implements Factory {
@Override
public Product getDrink() {
return null;
}
@Override
public Product getSnack() {
return new Bread();
}
}
6) 测试
public class FactoryTest {
public static void main(String[] args) {
Factory drinkFactory = new DrinkFactory();
Product p1 = drinkFactory.getDrink();
p1.info();
Factory snackFactory = new SnackFactory();
Product p2 = snackFactory.getSnack();
p2.info();
}
}
4.总结
优点:降低耦合;符合开-闭原则;符合单一职责原则;不使用静态工厂方法,可以形成基于继承的等级结构
缺点:难以扩展新种类产品