设计模式之工厂模式

 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的思想

缺点: 暂时没想到

注:学习设计模式重要的还是思想,不能倔!!!

刚开始学设计模式,可能总结的不太好,大佬勿喷~

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值