设计模式之工厂模式

1、核心本质:

-实例化对象,用工厂方法代替new操作。
-将选择实现类、创建对象统一管理和控制,从而将调用者跟我们的实现类解耦。

2、应用场景

-JDK中Calendar的getInstance方法
-JDBC中Connection对象的获取
-Hibernate中SessionFactory创建Session
-spring中IOC容器创建管理bean对象
-XML解析时的DocumentBuilderFactory创建解析器对象
-反射中Class对象的newInstance()

3、优点

实现了创建者和调用者的分离。

4、分类

-简单工厂模式
-工厂方法模式
-抽象工厂模式

5、代码示例

问题引出:这里用一个射击游戏做例子,CF中有各种不同的枪械,我们如何创造出不同的枪械呢?

普通方法:
设计模式之工厂模式_第1张图片

/**
 * 抽象接口:武器
 * @author ly1
 *
 */
public interface Weapon {
    void shot();
}
/**
 * 武器实现类:AK
 * @author ly1
 *
 */
public class AK implements Weapon{

    @Override
    public void shot() {
        System.out.println("AK后坐力大...");
    }

}
/**
 * 武器实现类:M4
 * @author ly1
 *
 */
public class M4 implements Weapon{

    @Override
    public void shot() {
        System.out.println("M4后坐力小...");
    }

}
/**
 * 客户端调用
 * @author ly1
 *
 */
public class Client {
    public static void main(String[] args) {
        Weapon w1 = new AK();
        Weapon w2 = new M4();

        w1.shot();
        w2.shot();
    }
}

普通方法不使用工厂类,使得调用类与每个类之间耦合很高。

简单工厂模式:
设计模式之工厂模式_第2张图片

/**
 * 抽象接口:武器
 * @author ly1
 *
 */
public interface Weapon {
    void shot();
}
/**
 * 武器实现类:AK
 * @author ly1
 *
 */
public class AK implements Weapon{

    @Override
    public void shot() {
        System.out.println("AK后坐力大...");
    }

}
/**
 * 武器实现类:M4
 * @author ly1
 *
 */
public class M4 implements Weapon{

    @Override
    public void shot() {
        System.out.println("M4后坐力小...");
    }

}
/**
 * 武器工厂类
 * @author ly1
 *
 */
public class WeaponFactory {

    public static Weapon create(String type){
        if(type.equals("M4")){
            return new M4();
        }else if(type.equals("AK")){
            return new AK();
        }else{
            return null;
        }
    }
}
/**
 * 客户端调用
 * @author ly1
 *
 */
public class Client {
    public static void main(String[] args) {
        Weapon w1 = WeaponFactory.create("AK");
        Weapon w2 = WeaponFactory.create("M4");

        w1.shot();
        w2.shot();
    }
}

简单工厂模式,在普通模式的基础上增加了工厂类,实现了创建者与调用者的分离。生产枪械集中在工厂类中完成,调用者只需通过传参完成类的创建,如果增加一种枪械,直接增加一个Weapon实现类,修改工厂类中少量代码就行了。

工厂方法模式:
设计模式之工厂模式_第3张图片

/**
 * 抽象接口:武器
 * @author ly1
 *
 */
public interface Weapon {
    void shot();
}
/**
 * 武器实现类:AK
 * @author ly1
 *
 */
public class AK implements Weapon{

    @Override
    public void shot() {
        System.out.println("AK后坐力大...");
    }

}
/**
 * 武器实现类:M4
 * @author ly1
 *
 */
public class M4 implements Weapon{

    @Override
    public void shot() {
        System.out.println("M4后坐力小...");
    }

}
/**
 * 抽象工厂接口
 * @author ly1
 *
 */
public interface WeaponFactory {
     Weapon createWeapon();
}
/**
 * 工厂的实现类:AK工厂
 * @author ly1
 *
 */
public class AKFactory implements WeaponFactory{

    @Override
    public Weapon createWeapon() {
        return new AK();
    }

}
/**
 * 工厂的实现类:M4工厂
 * @author ly1
 *
 */
public class M4Factory implements WeaponFactory{

    @Override
    public Weapon createWeapon() {
        return new M4();
    }

}
/**
 * 客户端调用
 * @author ly1
 *
 */
public class Client {
    public static void main(String[] args) {
        Weapon w1 = new AKFactory().createWeapon();
        Weapon w2 = new M4Factory().createWeapon();

        w1.shot();
        w2.shot();
    }
}

工厂方法模式符合面向对象的OCP(Open-Closed Principle,开闭原则),可以看做简单工厂模式的升级版。当增加一种新枪械的时候,不用修改已有的代码,直接增加一个Weapon实现类和一个WeaponFactory实现类即可。当然,也造成了类的数量的膨胀和调用的复杂性,随着枪械种类的增加,类的数量急剧增加,复杂度也随之增加。

抽象工厂模式:
问题变化:生产的不光有武器,还有角色、道具,然后有几种系列(即后面提到的产品族,也就是前面几种产品的组合),比如说为高端玩家生产高端武器系列,为低端玩家生产低端武器系列。
设计模式之工厂模式_第4张图片

/**
 * 武器抽象接口
 * @author ly1
 *
 */
public interface Weapon {
    void shot();
}

/**
 * 武器实现类:AK
 * @author ly1
 *
 */
class AK implements Weapon{

    @Override
    public void shot() {
        System.out.println("AK威力大...");
    }

}

/**
 * 武器实现类:M4
 * @author ly1
 *
 */
class M4 implements Weapon{

    @Override
    public void shot() {
        System.out.println("M4威力小...");
    }

}
/**
 * 角色抽象接口
 * @author ly1
 *
 */
public interface Role {
    void property();
}

/**
 * 角色实现类:赛斯
 * @author ly1
 *
 */
class Sise implements Role{

    @Override
    public void property() {
        System.out.println("我是赛斯,没有特殊属性!");
    }

}

/**
 * 角色实现类:潘多拉
 * @author ly1
 *
 */
class Pandora implements Role{

    @Override
    public void property() {
        System.out.println("我是潘多拉,身体娇小,不易被击中!");
    }

}
/**
 * 装备抽象接口
 * @author ly1
 *
 */
public interface Equipment {
    void property();
}

/**
 * 装备实现类:防弹衣
 * @author ly1
 *
 */
class Bulletproof implements Equipment{

    @Override
    public void property() {
        System.out.println("防弹衣减小伤害...");
    }

}

/**
 * 装备实现类:普通衣服
 * @author ly1
 *
 */
class CommonClothes implements Equipment{

    @Override
    public void property() {
        System.out.println("普通衣服无任何效果...");
    }

}
/**
 * 系列产品生产的抽象工厂
 * @author ly1
 *
 */
public interface Factory {
    Weapon createWeapon();
    Role createRole();
    Equipment createEquipment();
}
/**
 * 高端玩家系列产品生产工厂
 * @author ly1
 *
 */
public class GoodPlayerFactory implements Factory{

    @Override
    public Weapon createWeapon() {
        return new AK();
    }

    @Override
    public Role createRole() {
        return new Pandora();
    }

    @Override
    public Equipment createEquipment() {
        return new Bulletproof();
    }

}
/**
 * 低端玩家系列产品生产工厂
 * @author ly1
 *
 */
public class BadPlayerFactory implements Factory{

    @Override
    public Weapon createWeapon() {
        return new M4();
    }

    @Override
    public Role createRole() {
        return new Sise();
    }

    @Override
    public Equipment createEquipment() {
        return new CommonClothes();
    }

}
/**
 * 客户端调用
 * @author ly1
 *
 */
public class Client {
    public static void main(String[] args) {
        Factory good = new GoodPlayerFactory();
        Weapon w = good.createWeapon();
        Role r = good.createRole();
        Equipment e = good.createEquipment();
        w.shot();
        r.property();
        e.property();
    }
}

抽象工厂可以说是解决另一种新问题,即解决产品族问题,也就是不同产品类型之间组合的问题,比如增加一种中端玩家产品系列,使用AK武器、赛斯角色、防弹衣,直接增加一个工厂实现类就可以了。但是如果增加一种产品的话,就无能为力了,比如增加一个近身武器产品(即近身武器接口),有两种近身武器斧头和小刀(即两个实现类),高端玩家配备斧头,低端玩家配备小刀,那么所有的工厂类都得修改。

6、分析

1)简单工厂模式:

a、简单工厂模式也叫静态工厂模式,就是工厂类一般是使用静态方法,通过接收的参数的不同来返回不同的对象实例。
b、对于增加新产品无能为力!不修改代码的话,是无法扩展的。

2)工厂方法模式:

a、为了避免简单工厂模式的缺点,不完全满足OCP。
b、工厂方法模式和简单工厂模式最大的不同在于,简单工厂模式只有一个(对于一个项目或者一个独立模块而言)工厂类,而工厂方法模式有一组实现了相同接口的工厂类。

3)抽象工厂模式:

a、用来生产不同产品族的全部产品。(对于增加新的产品,无能为力;支持增加产品族)
b、抽象工厂模式是工厂方法模式的升级版本,在有多个业务品种、业务分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式。

7、总结

a、简单工厂和工厂方法相比,简单工厂模式用的较多。对于我们普通 的项目来说,修改少量代码是可以接受的,而且将创建类放在一个工厂类中完成;而虽然工厂方法模式遵循面向对象设计原则,但会增加复杂度,并且导致类的数量膨胀。
b、抽象工厂模式解决增加产品族的问题,但对于增减新的产品无能为力。

你可能感兴趣的:(设计模式)