工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
工厂模式主要分为三种形式
简单工厂模式(不属于GoF的23种设计模式中)
工厂方法模式
抽象工厂模式
简单来说,本质上工厂模式是对创建对象过程的一种封装。通过封装,让客户端无需在意对象创建的过程和逻辑。看看下面的例子。
本文部分解释摘录自 http://c.biancheng.net/view/1351.html
比如我们去一家餐厅。我们想要点餐吃饭。
那么可以看作是客户得到了饮料,食物,餐具,然后一一使用。
不使用工厂模式时是这样的
public static void main(String[] args) {
// 普通创建对象
Hamburger hamburger = new Hamburger();
Steak steak = new Steak();
hamburger.eat();
steak.eat();
}
然而这样的创建对象,语义上不清晰且需要在客户端中初始化对象。
毕竟给我们制作食物的是餐厅,所以我们可以把餐厅理解成一种工厂。我们客户向餐厅点单就行了。
首先,餐厅生产的食品Food,都可以食用,创建接口eat。
public interface Food {
void eat();
}
那么使用汉堡和牛扒就应该如下实现
public class Hamburger implements Food {
@Override
public void eat() {
System.out.println("吃汉堡,嘎嘎嘎");
}
}
public class Steak implements Food {
@Override
public void eat() {
System.out.println("吃牛扒,嘎嘎嘎");
}
}
那么餐厅,就可以作为生产这些产品的工厂
public class RestaurantFactory {
public Food getFood(String type) {
if (type == null)
return null;
else if (type.equalsIgnoreCase("hamburger"))
return new Cock();
else if (type.equalsIgnoreCase("steak"))
return new Hamburger();
return null;
}
}
有了餐厅工厂以后,客户下单就不需要自己去new食物了。直接问餐厅拿!
public static void main(String[] args) {
// 普通创建对象
Hamburger hamburger = new Hamburger();
Steak steak = new Steak();
hamburger.eat();
steak.eat();
// 利用简单工厂创建对象
RestaurantFactory rpf = new RestaurantFactory();
Food hamburger = rpf.getFood("hamburger");
Food steak = rpf.getFood("steak");
hamburger.eat();
steak.eat();
}
上面是普通创建,下面是简单工厂创建,最后会输出2次
吃汉堡,嘎嘎嘎
吃牛排,嘎嘎嘎
上面我们可以看到,我们把创建对象都写进了一个方法里。其实我们也可以分开写,一个方法获得一种对象也可以,看具体需求。
public class RestaurantFactory {
public Food getHamburger() {
return new Hamburger();
}
public Food getSteak() {
return new Steak();
}
}
静态工厂只是在普通工厂上做一些小小的改变,意味着,工厂里的创建对象方法改写为静态方法,如此以来,就不需要new Factory 再操作工厂生成对象了。
public class RestaurantFactory {
public static Food getHamburger() {
return new Hamburger();
}
public static Food getSteak() {
return new Steak();
}
}
每次需要创建新的对线的时候,就得去修改工厂类,这明显违背了面向对象设计中的“开闭原则”。
工厂方法在简单工厂上做了抽象处理。
把具体工厂抽象出了一个超级工厂,所有的具体工厂都实现这个抽象超级工厂。客户端通过访问具体工厂的工厂方法来创建产品。
工厂方法模式的主要角色如下。
// 抽象工厂
public abstract class FoodAbstractFactory {
public abstract Food getFood();
}
// 具体工厂 麦当劳, Hamburger实现Food接口
public class McDonaldFactory extend FoodAbstractFactoty {
@Override
public Food getFood() {
return new Hamburger();
}
}
// 具体工厂 咖啡厅, Steak实现Food接口
public class CafeFactory extend FoodAbstractFactoty {
@Override
public Food getFood() {
return new Steak();
}
}
// Main函数
public static void main(String[] args) {
// 工厂方法创建对象
FoodAbstractFactory mcDonald = new McDonaldFactory();
FoodAbstractFactory cafe = new CafeFactory();
Food hamburger = mcDonald.getFood();
Food steak = cafe.getFood();
hamburger.eat();
steak.eat();
}
工厂方法模式通常适用于以下场景。
工厂方法模式的主要优点有:
其缺点是:
当需要生成的产品不多且不会增加,一个具体工厂类就可以完成任务时,可删除抽象工厂类。这时工厂方法模式将退化到简单工厂模式
前面介绍的工厂方法模式中考虑的是一类产品的生产,如畜牧场只养动物、电视机厂只生产电视机、计算机软件学院只培养计算机软件专业的学生等。
同种类称为同等级,也就是说:工厂方法模式只考虑生产同等级的产品,但是在现实生活中许多工厂是综合型的工厂,能生产多等级(种类) 的产品,如农场里既养动物又种植物,电器厂既生产电视机又生产洗衣机或空调,大学既有软件专业又有生物专业等。
本节要介绍的抽象工厂模式将考虑多等级产品的生产,将同一个具体工厂所生产的位于不同等级的一组产品称为一个产品族
抽象工厂的意义是确实比较抽象。。。它主要用于创建 对象家族 。下面举例说明,更好理解它主要解决的问题。
比如我现在手机上安装了一款App,我想在这个App上实现换肤功能。(包括配色和ui风格)
那么,我们就可以理解为,换肤功能就是一个抽象工厂,而功能中提供的每一种皮肤,就是一个具体工厂类。
每当我们修改了皮肤主题,一般都会需要我们重启App,于是App会根据已选的皮肤主题,找到对应的具体皮肤主题工厂,进行UI初始化,包括ui配色,button风格,slider特效等等......
在以上的换肤过程里,我们可以发现,皮肤主题工厂最终初始化出来的对象们都是不同类的,比如 Color,Button,Slider,Bar,Table。那么以上这些类实例就可以看作是主题工厂产生的对象家族。
上面的解释如果不太明白,就直接看代码吧。还是餐厅例子。餐厅除了食物,还会生产饮品,餐具等等。也就是说,食物,饮品和餐具就是餐厅抽象工厂定义的对象家族。看代码
// 抽象餐厅工厂
public abstract class RestaurantFactory {
public abstract Food getFood();
public abstract Drinks getDrinks();
public abstract Item getItem();
}
// 具体工厂 麦当劳, Hamburger实现Food接口,Cock实现Drinks,Tissue实现Item
public class McDonaldFactory extend FoodAbstractFactoty {
@Override
public Food getFood() {
return new Hamburger();
}
@Override
public Drinks getDrinks() {
return new Cock();
}
@Override
public Item getItem() {
return new Tissue();
}
}
// 具体工厂 咖啡厅, Steak实现Food接口,Coffee实现Drinks,Knife实现Item
public class CafeFactory extend FoodAbstractFactoty {
@Override
public Food getFood() {
return new Steak();
}
@Override
public Drinks getDrinks() {
return new Coffee();
}
@Override
public Item getItem() {
return new Knife();
}
}
// Main函数
public static void main(String[] args) {
// 抽象工厂创建对象
FoodAbstractFactory mcDonald = new McDonaldFactory();
FoodAbstractFactory cafe = new CafeFactory();
Food hamburger = mcDonald.getFood();
Drinks cock = mcDonald.getDrinks();
Item tissue = mcDonald.getItem();
Food steak = cafe.getFood();
Drinks coffee = cafe.getDrinks();
Item knife = cafe.getItem();
hamburger.eat();
steak.eat();
cock.drink();
coffee.drink();
tissue.use();
knift.use();
}
抽象工厂模式最早的应用是用于创建属于不同操作系统的视窗构件。如 java 的 AWT 中的 Button 和 Text 等构件在 Windows 和 UNIX 中的本地实现是不同的。
抽象工厂模式通常适用于以下场景:
抽象工厂模式的扩展有一定的“开闭原则”倾斜性:
另一方面,当系统中只存在一个等级结构的产品时,抽象工厂模式将退化到工厂方法模式。
原文:https://www.cnblogs.com/roy7sang/p/13634008.html