首先举一个例子:
我们现在去一家饭馆吃饭,点什么我们需要告诉餐馆我们需要什么:
public interface Restaurant {
void cook();
}
public class Duck implements Restaurant {
@Override
public void cook() {
System.out.println("来份北京烤鸭");
}
}
public class Fish implements Restaurant {
@Override
public void cook() {
System.out.println("来一份剁椒鱼头");
}
}
public class Meet implements Restaurant {
@Override
public void cook() {
System.out.println("炒了一盘牛肉");
}
}
public class Test {
public static void main(String[] args) {
Restaurant restaurant1 = new Meet();
restaurant1.cook();
Restaurant restaurant2 = new Duck();
restaurant2.cook();
}
}
我们观察上面的代码,虽然很好的完成了任务,但是,我们的三个实现类和和借口紧密的绑定到了一起,这意味着我们的代码耦合出现严重问题,不利于以后的维护,试想我们点餐能不能直接看菜单后让服务员告诉餐馆,而不是我们实际告诉餐馆
将“类实例化的操作”与“使用对象的操作”分开,让使用者不用知道具体参数就可以实例化出所需要的“产品”类,从而避免了在客户端代码中显式指定,实现了解耦。
修改代码
public class Waiter {
private static final int MENU_MEET = 1;
private static final int MENU_FISH = 2;
private static final int MENU_DUCK = 3;
public static Restaurant getMenu(int menuType) {
switch (menuType) {
case 1:
return new Meet();
case 2:
return new Fish();
case 3:
return new Duck();
default:
return new Rubbish();
}
}
}
public static void main(String[] args) {
// 客人再点餐的话就可以直接找到该服务员,让他负责跟餐馆沟通
Restaurant menu = Waiter.getMenu(1);
menu.cook();
}
1 它是一个具体的类,非接口 抽象类。有一个重要的getMenu()方法,利用if或者 switch创建产品并返回。
2 create()方法通常是静态的,所以也称之为静态工厂。
1 扩展性差(我想增加一种食物,除了新增一个食物产品类,还需要修改工厂类方法)
2 不同的产品需要不同额外参数的时候 不支持。
我们知道,上面的简单工厂模式有一个缺点是不同的产品需要不同的额外参数的时候,是不支持的,
而且如果使用时传递的type、Class出错,将不能得到正确的对象,容错率不高。
而多方法的工厂模式为不同产品,提供不同的生产方法,使用时 需要哪种产品就调用该种产品的方法,使用方便、容错率高。
增加一个工厂
public class CookFactor {
public static Restaurant getMeet(){
return new Meet();
}
public static Restaurant getFish(){
return new Fish();
}
public static Restaurant getDuck(){
return new Duck();
}
}
public class Test {
public static void main(String[] args) {
// 需要meet直接调用getmeet
Restaurant meet = CookFactor.getMeet();
meet.cook();
Restaurant duck = CookFactor.getDuck();
duck.cook();
}
}
工厂方法模式,又称工厂模式、多态工厂模式和虚拟构造器模式,通过定义工厂父类负责定义创建对象的公共接口,而子类则负责生成具体的对象。
将类的实例化(具体产品的创建)延迟到工厂类的子类(具体工厂)中完成,即由子类来决定应该实例化(创建)哪一个类。
工厂一旦需要生产新产品就需要修改工厂类的方法逻辑,违背了“开放 - 关闭原则
即简单工厂模式的缺点
之所以可以解决简单工厂的问题,是因为工厂方法模式把具体产品的创建推迟到工厂类的子类(具体工厂)中,此时工厂类不再负责所有产品的创建,而只是给出具体工厂必须实现的接口,这样工厂方法模式在添加新产品的时候就不修改工厂类逻辑而是添加新的工厂子类,符合开放封闭原则,克服了简单工厂模式中缺点
步骤1: 创建抽象工厂类,定义具体工厂的公共接口;
步骤2: 创建抽象产品类 ,定义具体产品的公共接口;
步骤3: 创建具体产品类(继承抽象产品类) & 定义生产的具体产品;
步骤4:创建具体工厂类(继承抽象工厂类),定义创建对应具体产品实例的方法;
步骤5:外界通过调用具体工厂类的方法,从而创建不同具体产品类的实例
// 抽象工厂类
public abstract class CookFactor2 {
/**
* 生产食物
* @return
*/
public abstract Restaurant creatRestaurant();
}
// 其实现类(获取具体产品)
public class DuckFactor extends CookFactor2 {
@Override
public Restaurant creatRestaurant() {
return new Duck();
}
}
// 其实现类(获取具体产品)
public class FishFactor extends CookFactor2 {
@Override
public Restaurant creatRestaurant() {
return new Fish();
}
}
public class Test {
public static void main(String[] args) {
Restaurant restaurant = new DuckFactor().creatRestaurant();
restaurant.cook();
Restaurant restaurant1 = new FishFactor().creatRestaurant();
restaurant1.cook();
}
}
简单工厂模式需要修改工厂类的判断逻辑
简单工厂中的工厂类存在复杂的switch逻辑判断
简单工厂模式的工厂类使用静态工厂方法
工厂模式可以说是简单工厂模式的进一步抽象和拓展,在保留了简单工厂的封装优点的同时,让扩展变得简单,让继承变得可行,增加了多态性的体现。
抽象工厂模式,即Abstract Factory Pattern,提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类;具体的工厂负责实现具体的产品实例。
抽象工厂模式与工厂方法模式最大的区别:抽象工厂中每个工厂可以创建多种类的产品;而工厂方法每个工厂只能创建一类
允许使用抽象的接口来创建一组相关产品,而不需要知道或关心实际生产出的具体产品是什么,这样就可以从具体产品中被解耦。
每个工厂只能创建一类产品
步骤1: 创建抽象工厂类,定义具体工厂的公共接口;
步骤2: 创建抽象产品族类 ,定义抽象产品的公共接口;
步骤3: 创建抽象产品类 (继承抽象产品族类),定义具体产品的公共接口;
步骤4: 创建具体产品类(继承抽象产品类) & 定义生产的具体产品;
步骤5:创建具体工厂类(继承抽象工厂类),定义创建对应具体产品实例的方法;
步骤6:客户端通过实例化具体的工厂类,并调用其创建不同目标产品的方法创建不同具体产品类的实例
选择食物,我们可以添加口味
// 食物的生产接口工厂类
public interface CookFactor3 {
/**
* 生产食物
* @return
*/
Restaurant creatRestaurant();
/**
* 选择口味
* @return
*/
Taste chooseTaste();
}
// 味道的接口工厂类
public interface Taste {
/**
* 味道
*/
void addTaste();
}
// 味道接口的实现类
public class Spicy implements Taste{
@Override
public void addTaste() {
System.out.println("辣味");
}
}
public class Light implements Taste {
@Override
public void addTaste() {
System.out.println("清淡");
}
}
/**
* 清淡的烤鸭
*/
public class DuckLight implements CookFactor3 {
@Override
public Restaurant creatRestaurant() {
return new Duck();
}
@Override
public Taste chooseTaste() {
return new Light();
}
}
/**
* 辣牛肉
*/
public class MeetSpicy implements CookFactor3 {
@Override
public Restaurant creatRestaurant() {
return new Meet();
}
@Override
public Taste chooseTaste() {
return new Spicy();
}
}
public class Test {
public static void main(String[] args) {
CookFactor3 cookFactor3=new DuckLight();
cookFactor3.creatRestaurant().cook();
cookFactor3.chooseTaste().addTaste();
CookFactor3 cookFactor31= new MeetSpicy();
cookFactor31.creatRestaurant().cook();
cookFactor31.chooseTaste().addTaste();
}
}
抽象工厂模式非常针对2个维度描述的产品的构造问题。取其中一个维度作为产品族(也就是对应一个具体工厂),另外一个维度作为产品族下的具体产品。从这个角度说,抽象工厂模式是在工厂模式基础上,做了一个维度的升级。
举例,比如商务男装,商务女装,时尚男装,时尚女装的选择问题。取男装为一个产品族,对应一个工厂;取女装作为一个产品族,对应一个工厂。每个工厂中会生产多种类型(商务或者时尚)的衣服。