简单工厂:简单工厂(也叫静态工厂) 一个具体工厂类里面通过一个静态方法去获取某个抽象产品的子产品。
比如你在自助贩卖机去买矿泉水:有怡宝,娃哈哈,百岁山。他们的价格为2块,1块,3块。这时候你就需要确定你想喝哪款,
需要传递一个水标识的信息给贩卖机,贩卖机就返一个对应的支付码,支付完成后送对应的水。
代码:
//工厂类:利用反射是为了减少if/else
public class WaterFactory {
public static Water getInstants(String type){
Water water = null;
try {
Class temp = Class.forName("com.yuanping.sjms_demo.simpleFactory." +type);
water = (Water)temp.newInstance();
}catch (UnknownTypeException | ClassNotFoundException |InstantiationException | IllegalAccessException exception){
System.out.println("未找到对应类型的水");
}
return water;
}
}
//接口
public interface Water {
void print();
}
//具体实现类
public class Awater implements Water{
@Override
public void print() {
System.out.println("这是怡宝的水");
}
}
public class Bwater implements Water{
@Override
public void print() {
System.out.println("这是娃哈哈的水");
}
}
public class Cwater implements Water{
@Override
public void print() {
System.out.println("这是百岁山的水");
}
}
//枚举类
public enum WaterType {
YIBAO("Awater"),
WAHAHA("Bwater"),
BAISUISHAN("Cwater"),
;
WaterType(String typeName){
this.typeName = typeName;
}
private String typeName;
public String getTypeName() {
return typeName;
}
}
//测试类
public class DemoTest {
public static void main(String[] args) {
//测试简单工厂
WaterFactory.getInstants(WaterType.WAHAHA.getTypeName()).print();
}
}
问题:
继上图的逻辑,假如我要上饮料,但饮料跟水要分开。那就得要多个自助贩卖机。那就变成以下。这样看上去是不是可以合并成一个机器卖两种不同类型的饮品。
再看如果要上新的水,就需要改动静态方法源码(或者改枚举),需要一个水的具体实现。对开闭原则是不符合的。对于代码维护也大,改了源码你全部都得复测一遍吧。
工厂方法 :一个抽象工厂 多个具体的工厂 生产抽象工厂里的某一个具体产品。图的话就是上图,但改动点不一样。工厂方法是加工厂加具体水的实现,然后在具体业务代码中获取指定的工厂。简单工厂是改静态方法加具体水的实现。
代码:
//抽象工厂类,目的就是获取水
public abstract class WaterAbctFactory {
public abstract Water getWater();
}
//具体工厂,获取不同类型的水
public class AwaterFactory extends WaterAbctFactory{
@Override
public Water getWater() {
return new Awater();
}
}
public class BwaterFactory extends WaterAbctFactory{
@Override
public Water getWater() {
return new Bwater();
}
}
//测试类
public class Test {
public static void main(String[] args) {
WaterAbctFactory awaterFactory = new AwaterFactory();
awaterFactory.getWater().print();
}
问题:这种写法其实解决的是对源静态方法不修改的问题,但是代价就是新增了工厂。但最终还是没解决简单工厂的第二个问题,如果是买饮料,还需要一个自助机。
抽象工厂 一个抽象工厂类 多个具体的工厂 生产抽象工厂里的多个具体产品。该模式为工厂方法的升级,就是为了解决多个自助机问题。将多个方法合并成一个总的抽象类。如现在一个自助机买饮料是一个方法,买水是另一个方法,但都在一个自助机内。
代码:
//抽象工厂类
public abstract class WaterAbctFactory {
public abstract Water getWater();
public abstract Drink getDrink();
}
//饮料类
public class AdrinkFactory extends WaterAbctFactory{
@Override
public Water getWater() {
return null;
}
@Override
public Drink getDrink() {
return new Adrink();
}
}
public class BdrinkFactory extends WaterAbctFactory {
@Override
public Water getWater() {
return null;
}
@Override
public Drink getDrink() {
return new Bdrink();
}
}
//测试类
public class Test {
public static void main(String[] args) {
WaterAbctFactory awaterFactory = new AwaterFactory();
awaterFactory.getWater().print();
WaterAbctFactory adrinkFactory = new AdrinkFactory();
adrinkFactory.getDrink().print();
}
}
缺点:工厂类实现的方法比较多,有些不需要的方法也要实现。但这规范性很强,一般都是共性的代码便于管控。
总结
简单工厂:一个具体工厂类生产某一个抽象产品的不同子产品。
工厂方法:一个抽象工厂类,多个具体工厂类生产某一个抽象产品的不同子产品。
抽象工厂:一个抽象工厂类,多个具体工厂类生产某多个抽象产品的不同子产品。
需要生产单产品时 优先考虑工厂方法和简单工厂,如果只是简单的单体业务直接用简单工厂,其实就是避免if else的过多。
生产多产品用抽象工厂 这个模式其实在springMVC分层有类似的感觉。一般会在service中定义service,然后又实现具体类重写方法。然后可以指定bean名称
调用指定service的方法。