1.概念
工厂模式就是把客户类和工厂类分开。消费者任何时候需要某种产品,只需向工厂请求即可。消费者无须修改就可以接纳新产品。缺点是当产品修改时,工厂类也要做相应的修改。如:如何创建及如何向客户端提供。
工厂模式分为简单工厂模式、工厂方法模式和抽象工厂模式三类,依次逐步抽象,并具有一般性。其中简单工厂模式是工厂方法模式的一种特例。‘
2.设计原则
6.要依赖抽象,不要依赖具体类。(依赖倒置原则)
3.举例子
①简单工厂模式用的还是比较多的,且容易理解。相当于一个工厂加工好一个对象给客户。
有一个工厂是造汽车的,现在主要造宝马320、460、600和860这几款。那么首相想到的是宝马320是个对象,宝马460是个对象,。。。他们都是宝马车,也就是说宝马系列的大框架差不多,那么我们可以定义一个宝马抽象类。然后分别让320、460、600和860分别继承该宝马。
/**
* 简单工厂
*/
public class SimpleFactory {
abstract class BMW {
private String name;
public BMW(String name) {
this.name = name;
}
public void show() {
System.out.println(name+" be created!");
}
}
class BMW320 extends BMW {
public BMW320(String name) {
super(name);
}
}
class BMW460 extends BMW {
public BMW460(String name) {
super(name);
}
}
class BMW600 extends BMW {
public BMW600(String name) {
super(name);
}
}
class BMW860 extends BMW {
public BMW860(String name) {
super(name);
}
}
//定义一个简单工厂,此处因为是内部类里有静态方法所以需要static修饰静态内部类可创建静态方法,如非内部类,则无需变成静态类
//简单工厂模式又称静态工厂方法模式
static class Factory {
static BMW createBMW(int type) {
switch (type) {
case 320:
return new SimpleFactory().new BMW320("BMW320");
case 460:
return new SimpleFactory().new BMW460("BMW460");
case 600:
return new SimpleFactory().new BMW600("BMW600");
case 860:
return new SimpleFactory().new BMW860("BMW860");
}
return null;
}
}
//测试,定义一个工厂,然后客户想工厂订购了一辆320,然后顾客更换新车系列460。。。。
public static void main(String[] args) {
BMW bmw = Factory.createBMW(320);
bmw.show();
bmw = Factory.createBMW(460);
bmw.show();
bmw = Factory.createBMW(600);
bmw.show();
bmw = Factory.createBMW(860);
bmw.show();
}
}
运行测试用例后,得到下图:
② 工厂方法模式 定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
现在有一个工厂,他即生产收音机,也生产电视机,那么这个时候工厂采用工厂方法。分别让收音机的子工厂生产收音机,电视机的子工厂生产电视机
/**
* 工厂方法:
* 在以下情况下,适用于工厂方法模式:
* (1) 当一个类不知道它所必须创建的对象的类的时候。
* (2) 当一个类希望由它的子类来指定它所创建的对象的时候。
* (3) 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。
*/
public class FactoryMethod {
//定义该工厂具有的产品接口
interface Product {
public void describe();
}
//定义具体的收音机产品
class Radio implements Product {
public Radio() {
System.out.println("收音机出生了。。。");
}
public void describe() {
System.out.println("我是Radio,大家好。。。");
}
}
//定义具体的电视机产品
class TV implements Product {
public TV() {
System.out.println("TV出生了。。。");
}
public void describe() {
System.out.println("我是TV,大家好。。。");
}
}
//定义创建对象的接口
interface Factory {
public Product createProduct();
}
//定义一个专门生产电视的子工厂
class TVFactory implements Factory {
@Override
public Product createProduct() {
return new TV();
}
}
//定义一个专门生产收音机的子工厂
class RadioFactory implements Factory {
@Override
public Product createProduct() {
return new Radio();
}
}
//测试,电视机工厂生产的是电视机,收音机工厂生产的是收音机
public static void main(String[] args) {
test(new FactoryMethod().new TVFactory());
test(new FactoryMethod().new RadioFactory());
}
public static void test(Factory factory) {
Product product = factory.createProduct();
product.describe();
}
}
运行结果:
这时候也可以结合反射等方法,来更加的灵活创建。
③抽象工厂模式 提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
抽象工厂模式和工厂方法模式的区别就在于需要创建对象的复杂程度上。而且抽象工厂模式是三个里面最为抽象、最具一般性的。
现在有两个品牌,一个是苹果,一个是三星。苹果推出了手机和笔记本,三星也推出了手机和笔记本。现在有人就是只卖一个品牌的东西,那么这个时候满足抽象模式的设计点即多个产品族里系统只消费其中一个产品族。代码设计,从产品的角度来看,可以定义手机一个产品接口和笔记本一个产品接口,从工厂这边看,一个苹果厂家和三星厂家,同时设计苹果专柜和三星专柜供用户购买。
/**
* 抽象工厂模式 提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类
* 抽象工厂:
* (1) 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有形态的工厂模式都是重要的。
* (2) 这个系统有多于一个的产品族,而系统只消费其中某一产品族。
* (3) 同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。
* (4) 系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。
*/
public class AbstractFactory {
//定义产品,从产品角度上分析
interface Phone {
public void describe();
}
interface Notebook {
public void describe();
}
class IPhone implements Phone {
@Override
public void describe() {
System.out.println("苹果6出来了。。");
}
}
class SamPhone implements Phone {
@Override
public void describe() {
System.out.println("NoteIV出来了。。");
}
}
class MAC implements Notebook {
@Override
public void describe() {
System.out.println("pro mac 最新版。。");
}
}
class SamNotebook implements Notebook {
@Override
public void describe() {
System.out.println("SAM Notebook最新版。。");
}
}
//定义工厂,从工厂角度分析
interface Apple {
public IPhone createIPhone();
public MAC createMAC();
}
interface SamSung {
public SamPhone createSamPhone();
public SamNotebook createSamNotebook();
}
class AppleShoppe implements Apple {
@Override
public IPhone createIPhone() {
return new IPhone();
}
@Override
public MAC createMAC() {
return new MAC();
}
}
class SamSungShoppe implements SamSung {
@Override
public SamPhone createSamPhone() {
return new SamPhone();
}
@Override
public SamNotebook createSamNotebook() {
return new SamNotebook();
}
}
//测试
public static void main(String[] args) {
//苹果专柜卖的
Apple apple = new AbstractFactory().new AppleShoppe();
Phone iphone = apple.createIPhone();
iphone.describe();
Notebook mac = apple.createMAC();
mac.describe();
//另一个三星专柜卖的
SamSung samSung = new AbstractFactory().new SamSungShoppe();
Phone note = samSung.createSamPhone();
note.describe();
Notebook samNotebook = samSung.createSamNotebook();
samNotebook.describe();
}
}
运行结果如下:
4.总结
应用场景
工厂方法:
在以下情况下,适用于工厂方法模式:
(1) 当一个类不知道它所必须创建的对象的类的时候。
(2) 当一个类希望由它的子类来指定它所创建的对象的时候。
(3) 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。
抽象工厂:
(1) 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有形态的工厂模式都是重要的。
(2) 这个系统有多于一个的产品族,而系统只消费其中某一产品族。
(3) 同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。
(4) 系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。
三种工厂模式应用场景略有不同,可以根据实际需要来设计,也可以灵活定义工厂类型。加上反射机制,可以减少工厂的实例化。
更多参考