工厂模式—— 简单工厂模式、工厂方法模式、抽象工厂模式(java)

一 、前言

工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。

工厂模式可以分为三类:

  1. 简单工厂模式(Simple Factory)
  2. 工厂方法模式(Factory Method)
  3. 抽象工厂模式(Abstract Factory)

这三种模式从上到下逐步抽象,并且更具一般性。

GOF 在《设计模式》一书中将工厂模式分为两类:工厂方法模式 与 抽象工厂模式。
简单工厂模式 不在23种设计模式之中。
所以有人认为 简单工厂模式 不属于23种GOF 设计模式之一,也有人将简单工厂模式 看为工厂方法模式的一种特例。

区别

工厂方法模式: 抽象工厂模式:
一个抽象产品类,可以派生出多个具体产品类。 多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。 一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类只能创建一个具体产品类的实例。 每个具体工厂类可以创建多个具体产品类的实例。

区别:
工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。
工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。

二、简单工厂模式

简单工厂模式, 又称 静态工厂方法模式 。从命名上就可以看出这个模式一定很简单。它存在的目的很简单:定义一个用于创建对象的接口。

先来看看它的组成:

  1. 抽象产品:它一般是具体产品继承的父类或者实现的接口。

  2. 具体产品:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。

  3. 工厂类:这是本模式的核心,含有一定的商业逻辑和判断逻辑,用来创建产品

2.1、优点

简单工厂模式的工厂类是整个模式的关键。其中包含了必要的逻辑判断,根据外部信息,决定究竟应该创建哪个具体类的对象。

通过使用简单工厂模式,用户无需了解对象如何创建的,只要传入必要信息就可以了。

2.2、缺点

工厂类集中了所有实例的创建逻辑,违背了高内聚责任分配原则。

随着系统中具体产品类不断增多,势必要不断修改工厂类,不易维护和扩展。同时,这也违背了开放封闭原则

2.3、代码

2.3.1、产品接口

public abstract class Computer {
	
    /**
     * 产品的抽象方法,由具体的产品类去实现
     */
    public abstract void start();
}

2.3.2、产品实现类

/**
 * 华硕电脑
 */
public class AsusComputer extends Computer {
	
    @Override
    public void start() {
        System.out.println("华硕电脑启动");
    }
}
/**
 * 惠普电脑
 */
public class HpComputer extends Computer{
	
    @Override
    public void start() {
        System.out.println("惠普电脑启动");
    }    
}
/**
 * 联想电脑
 */
public class LenovoComputer extends Computer{
	
    @Override
    public void start() {
        System.out.println("联想电脑启动");
    }    
}

2.3.3、工厂类

public class ComputerFactory {	
	
    public static Computer createComputer(String type){
        Computer mComputer=null;
        switch (type) {
            case "lenovo":
                mComputer=new LenovoComputer();
               break;
            case "hp":
                mComputer=new HpComputer();
                break;
            case "asus":
                mComputer=new AsusComputer();
                break;
        }
        return mComputer;
    }
}

2.3.4、测试类

public class Main {
	
	public static void main(String[] args) {
		ComputerFactory.createComputer("lenovo").start();
		ComputerFactory.createComputer("hp").start();
		ComputerFactory.createComputer("asus").start();
	}	
}
联想电脑启动
惠普电脑启动
华硕电脑启动

三、工厂方法模式

工厂方法是在设计模式中常用的一种模式,它属于设计模式的创造类型模式,主要用来创建对象。

  • 定义: 定义一个创建对象的接口,但让实现这个接口的类来决定要实例化那个类,工厂方法让类的实例化延迟到子类进行。
  • 类型: 创建型

3.1、使用场景

  • 创建对象需要大量重复的代码
  • 客户端(应用层)不依赖与产品类实例如何被创建、实现细节
  • 一个类通过其子类来指定创建那个对象

3.2、优点

  • 用户只需要关心所需产品的对应工厂,无序关心创建细节
  • 加入新的产品符合开闭原则,提高扩展性

3.3、缺点

  • 类的个数容易过多,增加复杂度
  • 增加了系统的抽象性和理解难度

3.4、代码

3.4.1、产品接口、工厂接口

/**
 * 冰箱接口
 */
public interface IFridge {
	
    //获取品牌名
    String getBrandName();

    //获取价格
    double getPrice();
}
/**
 * 冰箱工厂接口
 */
public interface IFridgeFactory {

    IFridge getIRefrigerator();
}

3.4.2、产品实现类

/**
 * 格力冰箱
 */
public class GeliFridge implements IFridge {
	
    @Override
    public String getBrandName() {
        return "格力冰箱";
    }

    @Override
    public double getPrice() {
        return 3999;
    }
}
/**
 * 海尔冰箱
 */
public class HaierFridge implements IFridge {
	
    @Override
    public String getBrandName() {
        return "海尔冰箱";
    }

    @Override
    public double getPrice() {
        return 5999;
    }
}
/**
 * 美的冰箱
 */
public class MeideFridge implements IFridge {
    @Override
    public String getBrandName() {
        return "美的冰箱";
    }

    @Override
    public double getPrice() {
        return 2999;
    }
}

3.4.3、工厂实现类

/**
 * 格力冰箱工厂
 */
public class GeliFridgeFactory implements IFridgeFactory {
    @Override
    public IFridge getIRefrigerator() {
        return new GeliFridge();
    }
}
/**
 * 海尔冰箱工厂
 */
public class HaierFridgeFactory implements IFridgeFactory {
	
    @Override
    public IFridge getIRefrigerator() {
        return new HaierFridge();
    }
}
/**
 * 美的冰箱工厂
 */
public class MeideFridgeFactory implements IFridgeFactory {
    @Override
    public IFridge getIRefrigerator() {
        return new MeideFridge();
    }
}

3.4.4、测试类

/**
 * 测试类
 */
public class Test {

	public static void main(String[] args) {
		
		IFridgeFactory haierFridgeFactory = new HaierFridgeFactory();
		IFridgeFactory geliFridgeFactory = new GeliFridgeFactory();
		IFridgeFactory mmeideFridgeFactory = new MeideFridgeFactory();
		
		IFridge refrigerator = haierFridgeFactory.getIRefrigerator();

		System.out.println("您购买了:" + refrigerator.getBrandName() + ",您需要支付:" + refrigerator.getPrice());
	}
}
您购买了:海尔冰箱,您需要支付:5999.0

四、抽象工厂模式

有时候我们希望一个工厂可以生产多种产品,比如冰箱冰箱工厂中既可以生产冰箱又可以生产洗衣机、空调。很显然我们上篇文章中介绍的工厂方法是不能满足我们的需求,这个时候我们就需要用到抽象工厂。

  • 定义:提供一个创建一系列相关或相互依赖的对象的接口
  • 无序指定他们具体的类
  • 类型:创建型

4.1、适用场景

  • 客户端(应用层)不需要依赖与产品类实例如何被创建、实现细节
  • 强调一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量重复代码
  • 提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现

4.2、优点

  • 具体产品在应用层 代码隔离,无需关心创建细节
  • 将一个系列的产品族统一到一起创建

4.3、缺点

  • 规定了所有可能被创建的产品集合,产品组种扩展新的产品比较困难,需要修改抽象工厂的接口
  • 增加了系统的抽象性和理解难度

4.4、分析:

  • 抽象方法是对工厂方法的进一步拓展
  • 工厂工厂方法针对的是产品等级结构
  • 抽象方法针对于的是产品族
  • 加入我们想要创建海尔冰箱、海尔洗衣机、海尔空调;格力冰箱、格力洗衣机、格力空调;美的冰箱、美的洗衣机、美的空调;如果我们采用工厂方法的话,就需要9个工厂类,如果采用抽象工厂则需要3个类就可以完成。因此抽象工厂相比较工厂方法极大的减少了类的创建

4.5、代码

4.5.1、产品接口

/**
 * 空调
 */
public interface IAirConditioner {
    //品牌
    String brand();
    //制冷
    void refrigeration();
    //制热
    void heating();
}


/**
 * 洗衣机
 */
public interface IWasher {
    String brand();
    //洗涤
    void washing();
}


/**
 * 冰箱
 */
public interface IFridge {
    String brand();
    //储藏
    void coldStorage();
    //冷冻
    void freeze();
}

4.5.2、产品实现类

海尔家电产品

/**
 * 海尔空调
 */
 class HaierAirConditioner implements IAirConditioner {
    @Override
    public String brand() {
        return "海尔空调";
    }
    @Override
    public void refrigeration() {
        System.out.println("开启制冷模式");
    }
    @Override
    public void heating() {
        System.out.println("开启制热模式");
    }
}

/**
 * 海尔洗衣机
 */
 class HaierWasher implements IWasher {
    @Override
    public String brand() {
        return "海尔洗衣机";
    }
    @Override
    public void washing() {
        System.out.println("标准洗涤");
    }
}

/**
 * 海尔冰箱
 */
 class HaierFridge implements IFridge {
    @Override
    public String brand() {
        return "海尔冰箱";
    }

    @Override
    public void coldStorage() {
        System.out.println("冷藏室");
    }
    @Override
    public void freeze() {
        System.out.println("冷冻室");
    }
}

格力空调家电产品

/**
 * 格力空调
 */
 class GeliAirConditioner implements IAirConditioner {
    @Override
    public String brand() {
        return "格力空调";
    }
    @Override
    public void refrigeration() {
        System.out.println("开启制冷模式");
    }

    @Override
    public void heating() {
        System.out.println("开启制热模式");
    }
}
 
/**
 * 格力洗衣机
 */
 class GeLiWasher implements IWasher {
    @Override
    public String brand() {
        return "格力洗衣机";
    }
    @Override
    public void washing() {
        System.out.println("标准洗涤");
    }
}

/**
 * 格力洗衣机
 */
 class GeliWasher implements IWasher {
    @Override
    public String brand() {
        return "格力洗衣机";
    }
    @Override
    public void washing() {
        System.out.println("标准洗涤");
    }
}

/**
 * 格力冰箱
 */
 class GeliFridge implements IFridge {
    @Override
    public String brand() {
        return "格力冰箱";
    }
    @Override
    public void coldStorage() {
        System.out.println("冷藏室");
    }
    @Override
    public void freeze() {
        System.out.println("冷冻室");
    }
}

4.5.3、抽象工厂接口

/**
 * 家电工厂接口
 */
public interface IApplianceFactory {
    //洗衣机
    IWasher getWasher();
    //空调
    IAirConditioner getAirConditioner();
    //冰箱
    IFridge getFridge();
}

4.5.4、工厂实现类

/**
 * 格力家电工厂
 */
public class GeliApplianceFactory implements IApplianceFactory {
    @Override
    public IWasher getWasher() {
        return new GeliWasher();
    }
    @Override
    public IAirConditioner getAirConditioner() {
        return new GeliAirConditioner();
    }
    @Override
    public IFridge getFridge() {
        return new GeliFridge();
    }
}
/**
 * 海尔家电工厂
 */
public class HaierApplianceFactory implements IApplianceFactory {
	
   @Override
    public IWasher getWasher() {
        return new HaierWasher();
    }
    
    @Override
    public IAirConditioner getAirConditioner() {
        return new HaierAirConditioner();
    }
    
   @Override
    public IFridge getFridge() {
        return new HaierFridge();
    }
}

4.5.5、测试代码

public class Main {

	public static void main(String[] args) {
		// 洗衣机
		IWasher washer = new GeliApplianceFactory().getWasher();
		String washerBrand = washer.brand();
		System.out.println("品牌:" + washerBrand);
		washer.washing();
		
		// 冰箱
		IFridge fridge = new HaierApplianceFactory().getFridge();
		String 	fridgeBrand = fridge.brand();
		System.out.println("品牌:" + fridgeBrand);
		fridge.coldStorage();
		fridge.freeze();
		
		// 空调
		IAirConditioner airConditioner = new HaierApplianceFactory().getAirConditioner();
		String airConditionerBrand = airConditioner.brand();
		System.out.println("品牌:" + airConditionerBrand);
		airConditioner.heating();
		airConditioner.refrigeration();
	}
}

运行结果:

品牌:格力洗衣机
标准洗涤
品牌:海尔冰箱
冷藏室
冷冻室
品牌:海尔空调
开启制热模式
开启制冷模式

转载: https://www.jianshu.com/p/4c7d0ee96094

发布了297 篇原创文章 · 获赞 263 · 访问量 114万+

猜你喜欢

转载自blog.csdn.net/xiaojin21cen/article/details/104556215