1、简单工厂模式(非23种设计模式当中的)
核心代码:
abstract class Coffee{
}
class AmericanoCoffee extends Coffee{
}
class LatteCoffee extends Coffee{
}
class SimpleCoffeeFactory {
public Coffee createCoffee(String type) {
Coffee coffee = null;
if("americano".equals(type)) {
coffee = new AmericanoCoffee();
} else if("latte".equals(type)) {
coffee = new LatteCoffee();
}
return coffee;
}
}
思想:
实际上就是通过一种多态的思想,让我们的具体商品去继承我们的抽象类
2、工厂方法模式
核心代码:
/**
* 抽象工厂
**/
public interface CoffeeFactory {
Coffee createCoffee();
}
/**
* 具体工厂
*
* 抽象产品为coffee,具体产品为LatteCoffee和AmericanCoffee
* 这种工厂模式可以通过不同的具体工厂创建出不同的具体产品
**/
public class LatteCoffeeFactory implements CoffeeFactory {
public Coffee createCoffee() {
return new LatteCoffee();
}
}
public class AmericanCoffeeFactory implements CoffeeFactory {
public Coffee createCoffee() {
return new AmericanCoffee();
}
}
/**
* 生产类
*
**/
public class CoffeeFactoryMethod {
private CoffeeFactory coffeeFactory;
public void setFactory(CoffeeFactory coffeeFactory){
this.coffeeFactory = coffeeFactory;
}
public Coffee createCoffee() {
Coffee coffee = coffeeFactory.createCoffee();
return coffee;
}
}
思想:
实际上是对简单工厂的一种优化做法,比如说我们上面的简单工厂,如果要加入一种新的商品的时候,不仅要让我们的商品去继承我们的抽象类,还要去修改我们的createCoffee()方法,则有违背我们的OCP原则,所以我们增加了一层工厂类,让这些工厂类来实现创建具体商品的行为为,后续如果我们要添加商品,则只需要去实现我们的工厂接口即可,不用修改CoffeeFactoryMethod类的源代码
优点:在某些条件下满足OCP原则
缺点: 1、添加一个商品需要添加一个相应的工厂类,可能会产生类爆炸
2、无法横向拓展,既如果添加其他类型的商品如甜品,则没办法实现我们的工厂接口
了,因此需要去修改CoffeeFactoryMethod的源代码,还是不满足OCP原则
3、抽象工厂模式
核心代码:
/**
* 抽象工厂
**/
public interface DessertFactory {
Coffee createCoffee();
Dessert createDessert();
}
/**
* 具体工厂
**/
public class AmericanDessertFactory implements DessertFactory {
public Coffee createCoffee() {
return new AmericanCoffee();
}
public Dessert createDessert() {
return new MatchaMousse();
}
}
public class ItalyDessertFactory implements DessertFactory {
public Coffee createCoffee() {
return new LatteCoffee();
}
public Dessert createDessert() {
return new Tiramisu();
}
}
/**
* 生产类
*
**/
public class CoffeeAbstractFactory {
private DessertFactory dessertFactory ;
public void setFactory(DessertFactory dessertFactory ){
this.dessertFactory = dessertFactory;
}
public Coffee createCoffee() {
Coffee coffee = dessertFactory.createCoffee();
return coffee;
}
public Dessert createDessert() {
Dessert dessert= dessertFactory.createDessert();
return dessert;
}
}
思想:
实际上也是对工厂方法的一种思想优化,正如上面所说的工厂方法缺点,当我们横向拓展的时候可能需要去修改源代码,而抽象工厂则不需要,当我们添加一个新的商品的时候,只需要让我们的工厂去实现我们顶级接口DessertFactory即可,然后实现方法,让工厂决定创建的对象。
优点:某些条件下满足了OCP原则
缺点:拿工厂方法来对比可以发现,工厂方法面向的是同类商品,如相同的咖啡等,而抽象工厂更强大一点,只需要我们的顶级接口定义的够高,就可以加入不同类的商品,只需要我们的实现类去完成相应的返回方法即可。但实际上,我们对于接口的定义可能不会太高,所以在横向加入其他产品族的时候,还是需要去修改我们的接口,所以在某些情况下,还是不满足OCP原则。
4、最终拓展方案
核心代码:
bean.properties
american=cn.com.supercoder.pattern.AmericanCoffee
latte=cn.com.supercoder.pattern.LatteCoffee
CoffeeFactory.java
public class CoffeeFactory {
private static Map<String,Coffee> map = new HashMap();
// 加载配置文件
static {
Properties p = new Properties();
InputStream is = CoffeeFactory.class.getClassLoader().getResourceAsStream("bean.properties");
try {
//加载我们的properties文件
p.load(is);
// 遍历Properties集合对象
Set<Object> keys = p.keySet();
for (Object key : keys) {
// 根据键获取值(全类名)
String className = p.getProperty((String) key);
// 获取Class对象
Class clazz = Class.forName(className);
// 实例化对象
Coffee obj = (Coffee) clazz.newInstance();
// 将对象以键值对的形式存入map
map.put((String)key,obj);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取对象时直接根据配置文件中的key获取对应的对象
**/
public static Coffee createCoffee(String name) {
return map.get(name);
}
}
思想:
目的还是为了解耦,所以采用的是反射+配置文件的形式来完成。
用了静态代码块是因为我们的配置文件只需要加载一次即可
优点:满足了OCP原则,有点借鉴于Spring当中IOC的思想
缺点: 暂时没想到
注:学习设计模式重要的还是思想,不能倔!!!
刚开始学设计模式,可能总结的不太好,大佬勿喷~