02.工厂模式设计思想
目录介绍
- 01.工厂模式设计
- 1.1 工厂模式类型
- 1.2 工厂模式思考
- 1.3 思考一个题目
- 02.简单工厂介绍
- 2.1 简单工厂背景
- 2.2 简单工厂定义
- 2.3 简单工厂结构
- 2.4 简单工厂案例
- 2.5 简单工厂分析
- 2.6 简单工厂场景
- 2.7 简单工厂不足
- 03.工厂方法介绍
- 3.1 工厂方法背景
- 3.2 工厂方法定义
- 3.3 工厂方法结构
- 3.4 工厂方法案例
- 3.5 工厂方法分析
- 3.6 工厂方法场景
- 3.7 工厂方法不足
- 04.抽象工厂介绍
- 4.1 抽象工厂背景
- 4.2 抽象工厂定义
- 4.3 抽象工厂结构
- 4.4 抽象工厂案例
- 4.5 抽象工厂分析
- 4.6 抽象工厂场景
- 4.7 抽象工厂不足
- 05.工厂模式总结
- 5.1 工厂设计总结
- 5.2 如何选择
- 5.3 更多内容推荐
01.工厂模式设计
1.1 工厂模式类型
一般情况下,工厂模式分为三种更加细分的类型:简单工厂、工厂方法和抽象工厂。
不过,在 GoF 的《设计模式》一书中,它将简单工厂模式看作是工厂方法模式的一种特例,所以工厂模式只被分成了工厂方法和抽象工厂两类。
实际上, 在这三种细分的工厂模式中,简单工厂、工厂方法原理比较简单,在实际的项目中也比较常用。而抽象工厂的原理稍微复杂点,在实际的项目中相对也不常用。
1.2 工厂模式思考
讲解的重点也不是原理和实现,因为这些都很简单,重点还是带你搞清楚应用场景。什么时候该用工厂模式?相对于直接 new 来创建对象,用工厂模式来创建究竟有什么好处呢?
1.3 思考一个题目
你现在是一个做咖啡的老板。你要在店里买各种咖啡,而这些咖啡中有的加冰,有的加奶,有的加糖。比如美式咖啡,拿铁咖啡,摩卡咖啡,巴西咖啡等等!你需要设计一个咖啡店点餐系统!
简单工厂实现:设计一个咖啡类(Coffee),并定义其两个子类(美式咖啡AmericanCoffee和拿铁咖啡LatteCoffee);再设计一个咖啡店类(CoffeeStore),咖啡店具有点咖啡的功能。
- 创造抽象产品角色,比如总结出很多咖啡都可能会,加糖,加冰,加奶,因此把它抽成抽象方法。
- 具体产品角色,这块有:美式咖啡类,拿铁咖啡类,摩卡咖啡等,这些都是具体的咖啡产品。
- 工厂角色。负责创建不同咖啡,为了简便高效地分配咖啡,设了根据类型(比如
american
,latte
)来提供不同的咖啡。
新增需求1: 后期我想要再增加一个或者多个新的咖啡,简单工厂这个案例则需要修改工厂角色,这个违背了开闭原则。那有什么好的方式解决呢?可以用工厂方法模式。
工厂方法实现:
- Product:抽象产品。这个和简单工厂模式代码一样,忽略!
- ConcreteProduct:具体产品。这个和简单工厂模式代码一样,忽略!
- Factory:抽象工厂。这块定义咖啡工厂接口,通过该接口子类可以自己实现咖啡创建。
- ConcreteFactory:具体工厂。这里主要是创建美式咖啡工厂类,创建拿铁咖啡工厂类。
新增需求2: 后期咖啡点业务增多,现在不仅生产咖啡,还要生产甜点,请用抽象工厂去实现咖啡店咖啡和甜点的生产。这个可以用到抽象工厂模式。
抽象工厂实现:
- AbstractFactory:抽象工厂。这个时候则需要抽象出生产甜品,生产咖啡的接口。
- ConcreteFactory:具体工厂。分别实现生产甜品的具体工厂,生产咖啡的具体工厂。
- AbstractProduct:抽象产品。这里把甜点抽象成一个产品,把咖啡抽象成一个产品。
- Product:具体产品。创建具体的美式咖啡,拿铁咖啡产品。创建具体的提拉米苏甜点,抹茶慕斯甜点。
02.简单工厂介绍
2.1 简单工厂背景
考虑一个简单的软件应用场景,一个软件系统可以提供多个外观不同的按钮(如圆形按钮、矩形按钮、菱形按钮等),这些按钮都源自同一个基类,不过在继承基类后不同的子类修改了部分属性从而使得它们可以呈现不同的外观。
如果我们希望在使用这些按钮时,不需要知道这些具体按钮类的名字,只需要知道表示该按钮类的一个参数,并提供一个调用方便的方法,把该参数传入方法即可返回一个相应的按钮对象,此时,就可以使用简单工厂模式。
2.2 简单工厂定义
简单工厂模式(Simple Factory Pattern):又称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
2.3 简单工厂结构
简单工厂模式包含如下角色:
- Factory:工厂角色 。工厂角色负责实现创建所有实例的内部逻辑
- Product:抽象产品角色 。抽象产品角色是所创建的所有对象的父类,负责描述所有实例所共有的公共接口
- ConcreteProduct:具体产品角色 。具体产品角色是创建目标,所有创建的对象都充当这个角色的某个具体类的实例。
2.4 简单工厂案例
创造抽象产品角色,比如总结出很多咖啡都可能会,加糖,加冰,加奶,因此把它抽成抽象方法。
// 咖啡类(父类)--抽象类
public abstract class Coffee {
//每个咖啡都有名字,所以抽取到父类,定义为抽象方法
public abstract String getName();
public void addMilk() {
System.out.println("加奶...");
}
public void addSugar() {
System.out.println("加糖...");
}
}
具体产品角色,这块有:美式咖啡类,拿铁咖啡类,摩卡咖啡等,这些都是具体的咖啡产品。
// 美式咖啡类 继承 咖啡类
public class AmericanCoffee extends Coffee {
@Override
public String getName() {
return "美式咖啡";
}
public void show() {
System.out.println("我是美式咖啡....");
}
}
// 拿铁咖啡类 继承 咖啡类
public class LatteCoffee extends Coffee {
@Override
public String getName() {
return "拿铁咖啡";
}
}
工厂角色。负责创建不同咖啡,为了简便高效地分配咖啡,设了根据类型(比如american
,latte
)来提供不同的咖啡。
// 咖啡工厂
public class SimpleFactory {
//提供方法,创建具体咖啡
public Coffee createCoffee(String type) {
Coffee coffee = null;
if ("american".equals(type)) {
coffee = new AmericanCoffee(); //多态
} else if ("latte".equals(type)) {
coffee = new LatteCoffee(); //多态
} else {
throw new RuntimeException("没有这种咖啡!");
}
return coffee;
}
}
尽管简单工厂模式的代码实现中,有多处 if 分支判断逻辑,违背开闭原则,但权衡扩展性和可读性,这样的代码实现在大多数情况下(比如,不需要频繁地添加不同类型咖啡)是没有问题的。
最后就是咖啡点通过不同类型创建不同的咖啡
private void test() {
// 创建咖啡店对象,进行点咖啡
CoffeeStore store = new CoffeeStore();
//隐含了多态,在工厂里
Coffee coffee = store.orderCoffee("american");
String name = coffee.getName();
System.out.println(name);
//加糖...
//加奶...
//美式咖啡
}
// 咖啡店类
public class CoffeeStore {
public Coffee orderCoffee(String type) {
//此处解除了咖啡店类和具体的咖啡类的依赖,降低了耦合
// 创建工厂对象目的是创建具体的咖啡
SimpleFactory sf = new SimpleFactory();
// 创建咖啡,返回具体的咖啡对象
Coffee coffee = sf.createCoffee(type);
coffee.addSugar();
coffee.addMilk();
// 将具体的咖啡对象返回
return coffee;
}
}
思考一下这种场景,假如我们要更换对象(即,添加一个新的咖啡品种),我们势必要需求修改SimpleCoffeeFactory的代码,违反了开闭原则。
2.5 简单工厂分析
将对象的创建和对象本身业务处理分离可以降低系统的耦合度,使得两者修改起来都相对容易。
简单工厂模式的要点在于:当你需要什么,只需要传入一个正确的参数,就可以获取你所需要的对象,而无须知道其创建细节。
简单工厂模式最大的问题在于工厂类的职责相对过重,增加新的产品需要修改工厂类的判断逻辑,这一点与开闭原则是相违背的。
2.6 简单工厂场景
在以下情况下可以使用简单工厂模式:
- 工厂类负责创建的对象比较少:由于创建的对象较少,不会造成工厂方法中的业务逻辑太过复杂。
- 客户端只知道传入工厂类的参数,对于如何创建对象不关心:客户端既不需要关心创建细节,甚至连类名都不需要记住,只需要知道类型所对应的参数。
模式应用场景
- JDK类库中广泛使用了简单工厂模式,如工具类java.text.DateFormat,它用于格式化一个本地日期或者时间。
- Java加密技术,获取不同加密算法的密钥生成器: KeyGenerator keyGen=KeyGenerator.getInstance("DESede");
2.7 简单工厂不足
缺点1: 使用简单工厂模式将会增加系统中类的个数,在一定程序上增加了系统的复杂度和理解难度。举个例子……
缺点2: 系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。举个例子……
缺点3: 由于工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。违反了高内聚的责任分配原则。
缺点4: 简单工厂模式中的if else判断非常多,完全是Hard Code,如果有一个新产品要加进来,就要同时添加一个新产品类,并且必须修改工厂类,再加入一个 else if 分支才可以, 这样就违背了 “开放-关闭原则”中的对修改关闭的准则了。当系统中的具体产品类不断增多时候,就要不断的修改工厂类,对系统的维护和扩展不利。
03.工厂方法介绍
3.1 工厂方法背景
现在对该系统进行修改,不再设计一个按钮工厂类来统一负责所有产品的创建,而是将具体按钮的创建过程交给专门的工厂子类去完成,我们先定义一个抽象的按钮工厂类,再定义具体的工厂类来生成圆形按钮、矩形按钮、菱形按钮等,它们实现在抽象按钮工厂类中定义的方法。
这种抽象化的结果使这种结构可以在不修改具体工厂类的情况下引进新的产品,如果出现新的按钮类型,只需要为这种新类型的按钮创建一个具体的工厂类就可以获得该新按钮的实例,这一特点无疑使得工厂方法模式具有超越简单工厂模式的优越性,更加符合“开闭原则”。
3.2 工厂方法定义
工厂方法模式(Factory Method Pattern)又称为工厂模式,也叫虚拟构造器(Virtual Constructor)模式或者多态工厂(Polymorphic Factory)模式,它属于类创建型模式。
在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。
3.3 工厂方法结构
工厂方法模式包含如下角色:
- Product:抽象产品。定义了产品的规范,描述了产品的主要特性和功能。
- ConcreteProduct:具体产品。实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。
- Factory:抽象工厂。提供了创建产品的接口,调用者通过抽象工厂访问具体工厂(多态)的工厂方法来创建产品对象。
- ConcreteFactory:具体工厂。主要是实现抽象工厂中的抽象方法,完成具体产品的创建。
3.4 工厂方法案例
创建抽象产品。这里抽象出咖啡的公共特性,比如总结出很多咖啡都可能会,加糖,加冰,加奶,因此把它抽成抽象方法。这个和简单工厂模式代码一样,忽略!
创建具体产品。这块有:美式咖啡类,拿铁咖啡类,摩卡咖啡等,这些都是具体的咖啡产品。这个和简单工厂模式代码一样,忽略!
创建抽象接口工厂。定义咖啡工厂接口,通过该接口子类可以自己实现咖啡创建。
// 定义咖啡工厂接口
public interface CoffeeFactory {
public abstract Coffee creatCoffee();
}
创建具体工厂。这里主要是创建美式咖啡工厂类,创建拿铁咖啡工厂类
// 创建拿铁咖啡工厂类 实现 咖啡工厂类接口
public class LatteCoffeeFactory implements CoffeeFactory{
@Override
public Coffee creatCoffee() {
return new LatteCoffee();
}
}
// 创建美式咖啡工厂类 实现 咖啡工厂类接口
public class AmericanCoffeeFactory implements CoffeeFactory {
@Override
public Coffee creatCoffee() {
return new AmericanCoffee();
}
}
最后就是咖啡点通过不同类型创建不同的咖啡。这个时候看看代码如下所示:
private void test() {
// 创建咖啡店类对象
CoffeeStore coffeeStore = new CoffeeStore();
//创建拿铁咖啡工厂,多态
CoffeeFactory coffeeFactory = new LatteCoffeeFactory();
//CoffeeFactory amerFactory = new AmericanCoffeeFactory();
coffeeStore.setCoffeeFactory(coffeeFactory);
// 点咖啡
Coffee coffee = coffeeStore.orderCoffee();
System.out.println(coffee.getName());
}
//咖啡店类
public class CoffeeStore {
private CoffeeFactory coffeeFactory;
public void setCoffeeFactory(CoffeeFactory coffeeFactory) {
this.coffeeFactory = coffeeFactory;
}
public Coffee orderCoffee(){
// 咖啡工厂来创建具体的咖啡
Coffee coffee = coffeeFactory.creatCoffee();
// 加配料
coffee.addMilk();
coffee.addSugar();
return coffee;
}
}
3.5 工厂方法分析
工厂方法模式是简单工厂模式的进一步抽象和推广。由于使用了面向对象的多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。
在工厂方法模式中,核心的工厂类不再负责所有产品的创建,而是将具体创建工作交给子类去做。这个核心类仅仅负责给出具体工厂必须实现的接口,而不负责哪一个产品类被实例化这种细节,这使得工厂方法模式可以允许系统在不修改工厂角色的情况下引进新产品。
在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节,用户只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名。
使用工厂方法模式的另一个优点是在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了。这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。
3.6 工厂方法场景
在以下情况下可以使用工厂方法模式:
- 一个类不知道它所需要的对象的类:在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体的产品对象由具体工厂类创建;客户端需要知道创建具体产品的工厂类。
- 一个类通过其子类来指定创建哪个对象:在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏代换原则,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。
- 将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定,可将具体工厂类的类名存储在配置文件或数据库中。
3.7 工厂方法不足
在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。
由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。
04.抽象工厂介绍
4.1 抽象工厂背景
在工厂方法模式中具体工厂负责生产具体的产品,每一个具体工厂对应一种具体产品,工厂方法也具有唯一性,一般情况下,一个具体工厂中只有一个工厂方法或者一组重载的工厂方法。但是有时候我们需要一个工厂可以提供多个产品对象,而不是单一的产品对象。
当系统所提供的工厂所需生产的具体产品并不是一个简单的对象,而是多个位于不同产品等级结构中属于不同类型的具体产品时需要使用抽象工厂模式。
抽象工厂模式与工厂方法模式最大的区别在于,工厂方法模式针对的是一个产品等级结构,而抽象工厂模式则需要面对多个产品等级结构,一个工厂等级结构可以负责多个不同产品等级结构中的产品对象的创建。
4.2 抽象工厂定义
抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,属于对象创建型模式。
4.3 抽象工厂结构
抽象工厂模式包含如下角色:
- AbstractFactory:抽象工厂。提供了创建产品的接口,它包含多个创建产品的方法,可以创建多个不同等级的产品。
- ConcreteFactory:具体工厂。主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建。
- AbstractProduct:抽象产品。定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品。
- Product:具体产品。实现了抽象产品角色所定义的接口,由具体工厂来创建,它 同具体工厂之间是多对一的关系。
4.4 抽象工厂案例
后期咖啡点业务增多,现在不仅生产咖啡,还要生产甜点,请用抽象工厂去实现咖啡店咖啡和甜点的生产。
实现咖啡抽象产品和具体产品,代码如下:
// 咖啡抽象类
public abstract class Coffee {
public abstract String getName();
public void addMilk(){
System.out.println("加奶...");
}
public void addSugar(){
System.out.println("加糖...");
}
}
// 美式咖啡类 继承 咖啡类
public class AmericanCoffee extends Coffee {
@Override
public String getName() {
return "美式咖啡";
}
public void show() {
System.out.println("我是美式咖啡....");
}
}
// 拿铁咖啡类 继承 咖啡类
public class LatteCoffee extends Coffee {
@Override
public String getName() {
return "拿铁咖啡";
}
}
实现甜品抽象产品和具体产品,代码如下:
// 抽象甜品类
public abstract class Dessert {
// 定义展示具体甜品的规范
public abstract void show();
}
// 具体甜品--提拉米苏类 继承 抽象甜品类
public class Tiramisu extends Dessert{
@Override
public void show() {
System.out.println("提拉米苏...");
}
}
// 具体甜品--抹茶慕斯类 继承 抽象甜品类
public class MatchaMousse extends Dessert {
@Override
public void show() {
System.out.println("抹茶慕斯...");
}
}
抽象工厂,这个时候则需要抽象出生产甜品,生产咖啡的接口。代码如下所示
//抽象工厂 生产咖啡类 生产甜品类
public interface DessertFactory {
// 生产咖啡
Coffee createCoffee();
// 生产甜品
Dessert createDessert();
}
具体工厂,分别实现生产甜品的具体工厂,生产咖啡的具体工厂。代码如下所示
// 意大利风味甜品工厂
// 生产拿铁咖啡和提拉米苏甜品
public class ItalyDessertFactory implements DessertFactory{
// 生产拿铁咖啡
@Override
public Coffee createCoffee() {
return new LatteCoffee();
}
// 生产提拉米苏
@Override
public Dessert createDessert() {
return new Tiramisu();
}
}
// 美式风味的甜品工厂
// 生美式咖啡 和 抹茶慕斯
public class AmericanDessertFactory implements DessertFactory{
// 生产美式咖啡
@Override
public Coffee createCoffee() {
return new AmericanCoffee();
}
// 生产抹茶慕斯
@Override
public Dessert createDessert() {
return new MatchaMousse();
}
}
最后就是咖啡点通过不同类型创建不同的咖啡,也可以点不同类型的甜品。这个时候看看代码如下所示:
private void test() {
// 创建意大利风味甜品工厂对象
// 该工厂生产拿铁咖啡 和提拉米苏
ItalyDessertFactory factory = new ItalyDessertFactory();
// 获取拿铁咖啡
Coffee coffee = factory.createCoffee();
System.out.println(coffee.getName());//拿铁咖啡
// 获取提拉米苏
Dessert dessert = factory.createDessert();
dessert.show();//提拉米苏...
// 创建美式风味的甜品工厂对象
//该工厂生产美式咖啡 和抹茶慕斯
AmericanDessertFactory factory1 = new AmericanDessertFactory();
// 获取美式咖啡
Coffee coffee1 = factory1.createCoffee();
System.out.println(coffee1.getName());//美式咖啡
// 获取抹茶慕斯
Dessert dessert1 = factory1.createDessert();
dessert1.show();//抹茶慕斯...
}
思考一下该案例
- 当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
- 当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。
4.5 抽象工厂分析
当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。这对一些需要根据当前环境来决定其行为的软件系统来说,是一种非常实用的设计模式。
增加新的具体工厂和产品族很方便,无须修改已有系统,符合“开闭原则”。
4.6 抽象工厂场景
在以下情况下可以使用抽象工厂模式:
- 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有类型的工厂模式都是重要的。
- 系统中有多于一个的产品族,而每次只使用其中某一产品族。
- 属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。
- 系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。
4.7 抽象工厂不足
在添加新的产品对象时,难以扩展抽象工厂来生产新种类的产品,这是因为在抽象工厂角色中规定了所有可能被创建的产品集合,要支持新种类的产品就意味着要对该接口进行扩展,而这将涉及到对抽象工厂角色及其所有子类的修改,显然会带来较大的不便。
开闭原则的倾斜性(增加新的工厂和产品族容易,增加新的产品等级结构麻烦)。
05.工厂模式总结
5.1 工厂设计总结
01.工厂模式设计
工厂模式分类,大概分为三种更加细分的类型:简单工厂、工厂方法和抽象工厂。一般情况下,使用简单工厂,工厂方法场景稍多。
工厂模式思考,主要要搞清楚应用场景。什么时候该用工厂模式?相对于直接 new 来创建对象,用工厂模式来创建究竟有什么好处呢?
思考一个题目,你要在店里买各种咖啡,而这些咖啡中有的加冰,有的加奶,有的加糖。比如美式咖啡,拿铁咖啡,摩卡咖啡,巴西咖啡等等!用简单工厂,工厂方法,抽象工厂分别实现。
02.简单工厂介绍
一句话概括简单工厂:可以根据参数的不同返回不同类的实例。
简单工厂模式包含如下角色:抽象产品角色,具体产品角色,工厂角色。
简单工厂实现:
- 创造抽象产品角色,比如总结出很多咖啡都可能会,加糖,加冰,加奶,因此把它抽成抽象方法。
- 具体产品角色,这块有:美式咖啡类,拿铁咖啡类,摩卡咖啡等,这些都是具体的咖啡产品。
- 工厂角色。负责创建不同咖啡,为了简便高效地分配咖啡,设了根据类型(比如
american
,latte
)来提供不同的咖啡。
03.工厂方法介绍
工厂方法模式:定义一个创建对象的接口(指的是抽象工厂),让子类(具体工厂)决定实例化哪个产品类对象。工厂方法使一个产品类的实例化延迟到其工厂的子类。
工厂方法实现:
- Product:抽象产品。这个和简单工厂模式代码一样,忽略!
- ConcreteProduct:具体产品。这个和简单工厂模式代码一样,忽略!
- Factory:抽象工厂。这块定义咖啡工厂接口,通过该接口子类可以自己实现咖啡创建。
- ConcreteFactory:具体工厂。这里主要是创建美式咖啡工厂类,创建拿铁咖啡工厂类。
04.抽象工厂介绍
抽象工厂模式:抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级(即,同种的产品)的产品,而抽象工厂模式可生产多个等级(即,多种产品)的产品。
抽象工厂实现:
- AbstractFactory:抽象工厂。这个时候则需要抽象出生产甜品,生产咖啡的接口。
- ConcreteFactory:具体工厂。分别实现生产甜品的具体工厂,生产咖啡的具体工厂。
- AbstractProduct:抽象产品。这里把甜点抽象成一个产品,把咖啡抽象成一个产品。
- Product:具体产品。创建具体的美式咖啡,拿铁咖啡产品。创建具体的提拉米苏甜点,抹茶慕斯甜点。
5.2 如何选择
简单工厂(Simple Factory)模式:
- 定义:简单工厂模式通过一个工厂类来创建对象,根据传入的参数或条件决定创建哪种具体对象。
- 特点:简单工厂模式只有一个工厂类,根据条件创建对象,隐藏了对象的创建细节。
- 适用场景:当需要根据条件创建不同类型的对象时,可以考虑使用简单工厂模式。
工厂方法(Factory Method)模式:
- 定义:工厂方法模式将对象的创建延迟到子类中,每个子类负责创建自己的对象。
- 特点:工厂方法模式通过定义一个抽象的工厂接口和多个具体的工厂类,每个工厂类负责创建一种具体对象。
- 适用场景:当需要创建多个相关对象,并且希望将对象的创建逻辑封装在具体的工厂类中时,可以考虑使用工厂方法模式。
抽象工厂(Abstract Factory)模式:
- 定义:抽象工厂模式提供一个接口,用于创建一系列相关或相互依赖的对象,而无需指定具体的类。
- 特点:抽象工厂模式通过定义抽象工厂接口和多个具体工厂类,每个具体工厂类负责创建一组相关的对象。
- 适用场景:当需要创建一系列相关的对象,并且希望将对象的创建逻辑封装在具体的工厂类中时,可以考虑使用抽象工厂模式。
5.3 更多内容推荐
模块 | 描述 | 备注 |
---|---|---|
GitHub | 多个YC系列开源项目,包含Android组件库,以及多个案例 | GitHub |
博客汇总 | 汇聚Java,Android,C/C++,网络协议,算法,编程总结等 | YCBlogs |
设计模式 | 六大设计原则,23种设计模式,设计模式案例,面向对象思想 | 设计模式 |
Java进阶 | 数据设计和原理,面向对象核心思想,IO,异常,线程和并发,JVM | Java高级 |
网络协议 | 网络实际案例,网络原理和分层,Https,网络请求,故障排查 | 网络协议 |
计算机原理 | 计算机组成结构,框架,存储器,CPU设计,内存设计,指令编程原理,异常处理机制,IO操作和原理 | 计算机基础 |
学习C编程 | C语言入门级别系统全面的学习教程,学习三到四个综合案例 | C编程 |
C++编程 | C++语言入门级别系统全面的教学教程,并发编程,核心原理 | C++编程 |
算法实践 | 专栏,数组,链表,栈,队列,树,哈希,递归,查找,排序等 | Leetcode |
Android | 基础入门,开源库解读,性能优化,Framework,方案设计 | Android |
23种设计模式
23种设计模式 & 描述 & 核心作用 | 包括 |
---|---|
创建型模式 提供创建对象用例。能够将软件模块中对象的创建和对象的使用分离 |
工厂模式(Factory Pattern) 抽象工厂模式(Abstract Factory Pattern) 单例模式(Singleton Pattern) 建造者模式(Builder Pattern) 原型模式(Prototype Pattern) |
结构型模式 关注类和对象的组合。描述如何将类或者对象结合在一起形成更大的结构 |
适配器模式(Adapter Pattern) 桥接模式(Bridge Pattern) 过滤器模式(Filter、Criteria Pattern) 组合模式(Composite Pattern) 装饰器模式(Decorator Pattern) 外观模式(Facade Pattern) 享元模式(Flyweight Pattern) 代理模式(Proxy Pattern) |
行为型模式 特别关注对象之间的通信。主要解决的就是“类或对象之间的交互”问题 |
责任链模式(Chain of Responsibility Pattern) 命令模式(Command Pattern) 解释器模式(Interpreter Pattern) 迭代器模式(Iterator Pattern) 中介者模式(Mediator Pattern) 备忘录模式(Memento Pattern) 观察者模式(Observer Pattern) 状态模式(State Pattern) 空对象模式(Null Object Pattern) 策略模式(Strategy Pattern) 模板模式(Template Pattern) 访问者模式(Visitor Pattern) |