一、new一个具体对象
从订单的服务项说起。
假如在第一个版本,产品的需求是仅仅支持洗车这一种类型的服务项。
当我们得到了这一需求后,在写服务项列表的需求时,写一个【洗车服务项】类,使用时new一个洗车服务项就可以啦,这也是最基础的操作。
随着业务的扩大,需求的增加,1种类型的服务项已经不能满足业务需求,需要增加之前的服务项到4种,面对这种情况,我们应该如何应对?
A、在原来代码的基础上,按需new出4种具体的服务项类型。
这种方法可以,但是...
如果随着业务的扩大,需求的增加,4种服务项已经不能满足业务的需求.....怎么办?
---针对接口编程,就可以隔离掉以后系统可能会发生的修改。why?如果是针对接口编程,通过java语言的多态性,就可以与任何新类实现该接口。
反之,当代码中使用大量的具体类时,就会比较麻烦,容易牵一发动全身,必须对老代码进行改变。也就是说,你的代码并非“对修改关闭”。想用新的具体类型来扩展代码,就必须重新 打开它。
所以,有没有解决办法呢?工厂模式就可以帮我们解决这种问题。
就是用来改变,并帮我们“找出会变化的方面,把它们从不变的部分分离出来”。
二、简单工厂模式
类的创建型模式,静态工厂方法模式。
实质:是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类,而这些产品类继承自一个父类或是接口的实例。
实现:定义一个工厂类,其可以直接被外界调用,来创建其他产品类的实例,被创建的实例通常具有共同的基类(抽象类)。
工厂负责创建具体的产品实例,面相抽象类编程,返回基类,而基类指针指向子类的实例:工厂创建出子类实例后返回。(多态性)父 父 = new 子;
![](https://img.haomeiwen.com/i11726732/ec07ad57311b45ee.png)
public class SimpleFactory {
// 简单工厂
public SimpleFactory() {
}
// 返回商品的具体实现
public AbsProduct createProduct(int type) {
if (type == 1) {
return new ConcreteProductA();
} else if (type == 2) {
return new ConcreteProductB();
}
return null;
}
}
// 商品基类
interface AbsProduct {
void productFuc();
}
// 商品实现类A
public class ConcreteProductA implements AbsProduct {
public ConcreteProductA() {
}
@Override
public void productFuc() {
// TODO Auto-generated method stub
System.out.println(getClass());
}
}
// 商品实现类B
public class ConcreteProductB implements AbsProduct {
public ConcreteProductB() {
}
@Override
public void productFuc() {
// TODO Auto-generated method stub
System.out.println(getClass());
}
}
1.优点:
将实例的创建和判断逻辑放在工厂,用户可以免除创建产品对象的责任和过程,只关注于如何“消费”产品。
用户无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,减少用户的开发成本。
2.缺点:违背开放-封闭原则:简单工厂模式需要修改工厂类的判断逻辑;
由于使用了静态工厂方法,静态方法不能被继承和重写,会造成工厂角色无法形成基于继承的等级结构。
三、工厂(方法)模式
描述:工厂方法模式,又称工厂模式、多态工厂模式和虚拟构造器模式。
实质:定义创建对象的公共接口,而子类则负责生成具体的对象。
作用:将类的实例化(具体产品的创建)延迟到工厂类的子类(具体工厂)中完成,即由子类来决定应该实例化(创建)哪一个类。
解决的问题:弥补简单工厂模式违背的“开放-关闭”原则。
-工厂方法模式把具体产品的创建下放到工厂类的子类(具体工厂)中,此时工厂类不再负责所有产品的创建,而只是给出具体工厂必须实现的接口,这样工厂方法模式在添加新产品的时候就不修改工厂类逻辑而是添加新的工厂子类,符合开放封闭原则,克服了简单工厂模式中缺点。
![](https://img.haomeiwen.com/i11726732/d7e079adeb4f07c0.png)
public abstract class AbsFactory {
public abstract AbsProduct createProduct();
}
public class ConcreteFactoryA extends AbsFactory {
@Override
public AbsProduct createProduct() {
return new ConcreteProductA();
}
}
public class ConcreteFactoryB extends AbsFactory {
@Override
public AbsProduct createProduct() {
return new ConcreteProductB();
}
}
// 商品基类
interface AbsProduct {
void productFuc();
}
// 商品实现类A
public class ConcreteProductA implements AbsProduct {
public ConcreteProductA() {
}
@Override
public void productFuc() {
// TODO Auto-generated method stub
System.out.println(getClass());
}
}
// 商品实现类B
public class ConcreteProductB implements AbsProduct {
public ConcreteProductB() {
}
@Override
public void productFuc() {
// TODO Auto-generated method stub
System.out.println(getClass());
}
}
//使用
AbsFactory factory = new ConcreteFactoryA();
AbsProduct product = factory.createProduct();
product.productFuc();
优点:
更符合开-闭原则:新增一种产品时,只需要增加相应的具体产品类和相应的工厂子类即可。
符合单一职责原则:每个具体工厂类只负责创建对应的产品
不使用静态工厂方法,可以形成基于继承的等级结构。
总结:工厂模式可以说是简单工厂模式的进一步抽象和拓展,在保留了简单工厂的封装优点的同时,让扩展变得简单,让继承变得可行,增加了多态性的体现。
缺点:每增加一个产品,相应的也要增加一个子工厂,加大了额外的开发量。
一个具体工厂只能创建一种具体产品。
四、抽象工厂模式
上面两种,都是通过工厂创造出具体的实现类。
而抽象工厂模式:生产抽象的产品,创建的产品是接口(Interface)。
抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。
根据里氏替换原则,任何接受父类型的地方,都应当能够接受子类型。
![](https://img.haomeiwen.com/i11726732/32d8a74c4df7dcbd.png)
抽象工厂我们举例一个生产Iphone零件的例子。
我们先定义产品,这里是生产零件,我们定义两个抽象产品,一个CPU,一个电池。这里我把两个接口写在了一起,当然你也可以分开写成两个。
public interface component {
public interface CPU {
void showCpuName();
}
public interface Battery {
void showBatteryCapacity();
}
}
然后我们定义CPU的具体产品,一个CPU9,一个CPU10
public class CPU9 implements component.CPU {
@Override
public void showCpuName() {
Log.d("AbstractFactory","CPU9");
}
}
public class CPU10 implements component.CPU {
@Override
public void showCpuName() {
Log.d("AbstractFactory","CPU10");
}
}
然后是两种电池产品,一个1000ma,一个1200ma
public class Battery1000ma implements component.Battery {
@Override
public void showBatteryCapacity() {
Log.d("AbstractFactory","battery is 1000ma");
}
}
public class Battery1200ma implements component.Battery {
@Override
public void showBatteryCapacity() {
Log.d("AbstractFactory","battery is 1200ma");
}
}
产品定义好了,我们来定义工厂了,依旧先用抽象类,抽象出工厂类的方法
public abstract class Factory {
public abstract component.CPU createCPU();
public abstract component.Battery createBattery();
}
抽象工厂模式的由来:
这里的抽象方法跟抽象工厂模式并无实际关系,而是因为工厂模式生产的产品,一个是component.CPU,一个是component.Battery。他们两个都是接口,都是抽象出来的,故得名抽象工厂模式。
Factory是一个抽象类,我们用接口一样可以实现工厂该有的功能,为啥不用接口呢?
因为抽象类不能实例化,接口是可以实例化的。如果实例化了Factory,再来操作createCPU/createBattery 就没有实际意义,直接用抽象类就杜绝了这种情况的发生。
接着我们看具体工厂的实现,这里我们将用不同的工厂对应不同的产品来举例
public class IPhone1Factory extends Factory {
@Override
public component.CPU createCPU() {
return new CPU9();
}
@Override
public component.Battery createBattery() {
return new Battery1000ma();
}
}
public class Iphone2Factory extends Factory {
@Override
public component.CPU createCPU() {
return new CPU10();
}
@Override
public component.Battery createBattery() {
return new Battery1200ma();
}
}
1、可以看到IPhone1Factory和Iphone2Factory两个工厂模式他们创建的产品相同,都是创建CPU和Battery这两个抽象产品。而这两个抽象产品又可以是同接口不同子类实例。
1、抽象工厂模式创建出来的是接口。
2、优缺点:
优点:分离接口与实现,面向接口编程,不关心具体细节,使其从产品实现解耦,抽象工厂模式在切换产品类的时候更加灵活容易。
缺点:难以支持新品种的产品。
如果要上升一个层次的话:
产品族:
产品等级结构,
微型计算机配件,这个系统所需要的产品族有两个,一个系列是PC系列,另一个系列是MAC系列。
产品等级结构也有两个,一个是RAM,一个是CPU。
“一般而言,有多少个产品等级结构,就会在工厂角色中发现多少个工厂方法。每一个产品等级结构中有多少个具体的产品,就有多少个产品族,也就会在工厂等级结构中发现多少个具体工厂。”
抽象工厂模式使用同一个 工厂等级结构负责这些不同产品等级结构产品对象的创建。
对于每一个产品族,都有一个具体工厂。而每一个具体工厂创建属于同一个产品族,但是分属于不同等级结构的产品。
通过引进抽象工厂模式,可以处理具有相同(或者相似)等级结构的多个产品族中的产品对象的创建问题。
五、应用
1、ViewModel的创建
![](https://img.haomeiwen.com/i11726732/d657b93f390862e6.png)
2、Retrofit 简单工厂模式
https://www.jianshu.com/p/006f77a80c3f
区别,应用场景
网友评论