基准类,一个接口两个实现产品类
//接口Milk
public interface Milk {
/**
* 获取牛奶的名称
* @return String 名字
*/
String getName();
}
/**
* 蒙牛牛奶类MengNiu
*/
public class MengNiu implements Milk {
@Override
public String getName() {
return "蒙牛牛奶";
}
}
/**
* 特仑苏牛奶类Telunsu
*/
public class Telunsu implements Milk {
@Override
public String getName() {
return "特仑苏";
}
}
1.简单工厂模式
1.1 最基本的实现
简单工厂常用的方法就是一个工厂类,里面包含很多if else结构 或者switch case:
/**
* 牛奶工厂类MilkSimpleFactory
*/
public class MilkSimpleFactory {
public Milk getMilk(String name){
if ("telunshu".equals(name)){
return new Telunsu();
}else if ("mengniu".equals(name)){
return new MengNiu();
}
System.out.println("没有找到你的牛奶");
return null;
}
}
测试:
@Test
public void testSimpleFactory(){
String name = "mengniu";
MilkSimpleFactory milkSimpleFactory = new MilkSimpleFactory();
Milk milk = milkSimpleFactory.getMilk(name);
String milkName= milk.getName();
System.out.println("牛奶的名称:"+milkName);;
}
1.2 通过Map集合实现
通过传入不同的参数返回不同的对象。实际在开发中其实也是可以通过Map集合来存储的,把key存为需要查询的内容(这个Map可以提前设置,也可以配置到配置文件里面)
/**
*牛奶工厂类MilkSimpleFactory 参数用map实现
*/
public class MilkSimpleFactory {
private Map<String, Milk> milkMap= new HashMap<>();
public static getMilk(String milkName){
//通过传入的
return map.get(milkName);
}
//通过bean设置milkMap
public void setMilkMap(Map milkMap){
this.milkMap=milkMap;
}
}
配置文件
<bean id="telunsu" class="com.wusu.Telunsu"/>
<bean id="mengNiu" class="com.wusu.MengNiu"/>
<bean id="milkMap" class="com.wusu.Factory">
<property name="map">
<map>
<entry key="telunsu" value-ref="telunsu"></entry> //这里value-ref是引用的上面设置的bean的id
<entry key="mengNiu" value-ref="mengNiu"></entry>
</map>
</property>
</bean>
1.3 通过反射技术实现
可以自己实现下
public class MilkSimpleFactory {
//可以在工厂类中添加任何你所需要的逻辑
public static Milk getMilk(String name){
//LoadClassUtils 这个可以是 一个工具类,根据(比如productA)反射技术实例化一个对象
return LoadClassUtils.Load(name).newInstance();
}
}
总结:每次需要新添加一个产品,普通实现需要修改类,不符合开闭原则,但是用Map来实现只需要修改配置文件即可,也是非常合适的
2.工厂方法模式
工厂方法模式就是对于做逻辑判断的条件放到客户端代码实现。让每一个产品都有一个工厂。
这里一个工厂接口,还有产品工厂的实现类
/**
* 工厂接口
*/
public interface Factory {
//获取牛奶公共方法
Milk getMilk();
}
/**
* 蒙牛工厂
*/
public class MengNiuFactory implements Factory {
@Override
public Milk getMilk() {
return new MengNiu();
}
}
/**
* 特仑苏工厂
*/
public class TelunsuFactory implements Factory{
@Override
public Milk getMilk() {
return new Telunsu();
}
}
测试:
public class TestFunFactory {
public static void main(String[] args) {
Factory factory = new MengNiuFactory();
System.out.println("蒙牛牛奶的名字:"+factory.getMilk().getName());
}
}
总结:
- 优点:相比简单工厂普通实现在代码做判断,实现了“开放-封闭”原则,
- 缺点:每新加一个类,都需要再次添加一个工厂的实现类。如果要添加大量的类,出现大量工厂类。而且用户使用的是否需要自己去找具体的工厂。
3.抽象工厂模式
工厂实现入下:
/**
* 牛奶抽象工厂类
*/
public abstract class AbstractMilkFactory {
/**
* 获取 蒙牛
* @return Milk
*/
public abstract Milk getMengNiu();
/**
* 获取特仑苏
* @return Milk
*/
public abstract Milk getTelunsu();
}
/**
* 工厂实现类
*/
public class MilkFactory extends AbstractMilkFactory {
@Override
public Milk getMengNiu() {
return new MengNiu();
}
@Override
public Milk getTelunsu() {
return new Telunsu();
}
}
测试
public class TestAbstractFactory {
public static void main(String[] args) {
MilkFactory factory = new MilkFactory();
Milk mengNiu = factory.getMengNiu();
System.out.println("蒙牛牛奶的名字:"+mengNiu.getName());
}
}
总结:抽象工厂模式相比工厂方法新建一个产品的时候不需要新建对应的工厂类,只需要在抽象类中新建一个方法并在实现类实现这个方法即可,符合开闭原则(可以新添加不修改原代码)