概述
定义一个用于创建对象的接口,让子类决定实例化哪一个类,
工厂模式的应用
Spring中通过getBean(“xxx”)获取Bean
为什么要使用工厂模式
创建对象的方式有很多种,可以通过new关键字,可以通过反射机制,可以通过clone()方式,那为什么还要使用工厂模式呢,new()在代码中最常用,可以他的灵活性太差了。
这段代码把对象的创建和使用放在一个类中,如果要进行修改引用类,换做另一个子类,那么必须修改loginAction的源代码,违反了开闭原则。最常用的解决方案就是把创建userdao对象的职责从loginAction类中移除,那么谁来创建userdao对象呢,答案是工厂类。
(1) 解耦 :把对象的创建和使用的过程分开
(2)降低代码重复: 如果创建某个对象的过程都很复杂,需要一定的代码量,而且很多地方都要用到,那么就会有很多的重复代码。
(3)降低维护成本 :由于创建过程都由工厂统一管理,所以发生业务逻辑变化,不需要找到所有需要创建对象B的地方去逐个修正,只需要在工厂里修改即可,降低维护成本。
1 简单工厂
简单工厂不是设计模式,他把实例化化的代码从应用代码中剥离,引入了创建者的概念,后续创建的实例如果需要改变,只需要改造创建这类即可。不能在运行期通过不同的方式去动态改变创建行为,因此存在一定的局限性,违反了我们的开闭原则,之主要靠循环语句实现。
角色分配:
1 工厂角色
2 抽象产品角色
3 具体产品角色
/**
* @auther wkk
* @date 2019/6/5 10:24
*/
public abstract class Coffee {
/**
* 获取coffee名称
* @return
*/
public abstract String getName();
}
/**
* 美式咖啡
* @author Lsj
*
*/
class Americano extends Coffee {
@Override
public String getName() {
return "美式咖啡";
}
}
/**
* 卡布奇诺
* @author Lsj
*
*/
class Cappuccino extends Coffee {
@Override
public String getName() {
return "卡布奇诺";
}
}
/**
* 拿铁
* @author Lsj
*
*/
class Latte extends Coffee {
@Override
public String getName() {
return "拿铁";
}
}
class SimpleFactory {
/**
* 通过类型获取Coffee实例对象
* @param type 咖啡类型
* @return
*/
public static Coffee createInstance(String type){
if("americano".equals(type)){
return new Americano();
}else if("cappuccino".equals(type)){
return new Cappuccino();
}else if("latte".equals(type)){
return new Latte();
}else{
throw new RuntimeException("type["+type+"]类型不可识别,没有匹配到可实例化的对象!");
}
}
public static void main(String[] args) {
Coffee latte = SimpleFactory.createInstance("latte");
System.out.println("创建的咖啡实例为:" + latte.getName());
Coffee cappuccino = SimpleFactory.createInstance("cappuccino");
System.out.println("创建的咖啡实例为:" + cappuccino.getName());
}
}
工厂模式
1.工厂方法模式应该是在工厂模式家族中是用的最多模式,一般项目中存在最多的就是这个模式,工厂方法模式是简单工厂的仅一步深化, 在工厂方法模式中,我们不再提供一个统一的工厂类来创建所有的对象,而是针对不同的对象提供不同的工厂。也就是说 每个对象都有一个与之对应的工厂类。
四个角色
1 抽象工厂
2 具体工厂
3 抽象产品
4 具体产品
使用场景
一个类不知道它所需要的对象的类:在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体的产品对象由具体工厂类创建;客户端需要知道创建具体产品的工厂类。
我们来改良一下上面的案例
/**
* 抽象工厂
*/
interface Factory {
public Coffee getCoffee();
}
class CappuccinoFactory implements Factory{
@Override
public Coffee getCoffee() {
return new Cappuccino();
}
}
class AmericanoFactory implements Factory{
@Override
public Coffee getCoffee() {
return new Americano();
}
}
class LatteFactory implements Factory{
@Override
public Coffee getCoffee() {
return new Latte();
}
}
class SimpleFactory {
public static void main(String[] args) {
Factory latteFactory=new LatteFactory();
System.out.println(latteFactory.getCoffee().getName());
Factory cappuccino=new CappuccinoFactory();
System.out.println(cappuccino.getCoffee().getName());
}
}
结果
拿铁
卡布奇诺
抽象工厂模式
在工厂方法模式中,其实我们有一个潜在意识的意识。那就是我们生产的都是同一类产品。抽象工厂模式是工厂方法的仅一步深化,在这个模式中的工厂类不单单可以创建一种产品,而是可以创建一组产品。
实例
interface Gun {
public void shooting();
}
interface Bullet {
public void load();
}
//ak类产品
class AK implements Gun{
@Override
public void shooting() {
System.out.println("shooting with AK");
}
}
class AK_Bullet implements Bullet {
@Override
public void load() {
System.out.println("Load bullets with AK");
}
}
//M4A1类产品
class M4A1 implements Gun {
@Override
public void shooting() {
System.out.println("shooting with M4A1");
}
}
class M4A1_Bullet implements Bullet {
@Override
public void load() {
System.out.println("Load bullets with M4A1");
}
}
/**
*抽象工厂
*/
interface Factory {
public Gun produceGun();
public Bullet produceBullet();
}
//具体工厂 生产ak
class AK_Factory implements Factory{
@Override
public Gun produceGun() {
return new AK();
}
@Override
public Bullet produceBullet() {
return new AK_Bullet();
}
}
//生产m4a1
class M4A1_Factory implements Factory{
@Override
public Gun produceGun() {
return new M4A1();
}
@Override
public Bullet produceBullet() {
return new M4A1_Bullet();
}
}
//测试
class Test {
public static void main(String[] args) {
Factory factory;
Gun gun;
Bullet bullet;
factory =new AK_Factory();
bullet=factory.produceBullet();
bullet.load();
gun=factory.produceGun();
gun.shooting();
factory =new M4A1_Factory();
bullet=factory.produceBullet();
bullet.load();
gun=factory.produceGun();
gun.shooting();
}
}
参考 1 https://www.cnblogs.com/carryjack/p/7709861.html
2 https://blog.csdn.net/qq_34337272/article/details/80472071
3 https://blog.csdn.net/lovelion/article/details/7523392