07GoF之三种工厂模式
GoF(Gang of Four):四人组,《Design Patterns: Elements of Reusable Object-Oriented Software》(《设计模式》)的作者,设计了23种设计模式.但时代发展,还有其它的设计模式,比如:JavaEE的设计模式(DAO模式、MVC模式等)。
● GoF23种设计模式可分为三大类:
○ 创建型(5个):解决对象创建问题。
■ 单例模式
■ 工厂方法模式
■ 抽象工厂模式
■ 建造者模式
■ 原型模式
○ 结构型(7个):一些类或对象组合在一起的经典结构。
■ 代理模式
■ 装饰模式
■ 适配器模式
■ 组合模式
■ 享元模式
■ 外观模式
■ 桥接模式
○ 行为型(11个):解决类或对象之间的交互问题。
■ 策略模式
■ 模板方法模式
■ 责任链模式
■ 观察者模式
■ 迭代子模式
■ 命令模式
■ 备忘录模式
■ 状态模式
■ 访问者模式
■ 中介者模式
■ 解释器模式
● 工厂模式是解决对象创建问题的,所以工厂模式属于创建型设计模式。这里为什么学习工厂模式呢?这是因为Spring框架底层使用了大量的工厂模式。
为什么学工厂模式?
Spring底层就是通过工厂模式+XML+反射机制实现的.
工厂模式的三种形态
**● 第一种:简单工厂模式(Simple Factory):不属于23种设计模式之一。简单工厂模式又叫做:静态工厂方法模式。简单工厂模式是工厂方法模式的一种特殊实现。**一个工厂对应一种产品.
● 第二种:工厂方法模式(Factory Method):是23种设计模式之一。一个工厂对应多种产品.
● 第三种:抽象工厂模式(Abstract Factory):是23种设计模式之一。一个工厂对应多种产品系列.
简单工厂模式
Spring中的BeanFactory就使用了简单工厂模式。
简单工厂模式的角色包括三个:
● 工厂类 角色
● 抽象产品 角色
● 具体产品 角色
简单工厂模式的优点:
● 客户端程序不需要关心对象的创建细节,需要哪个对象时,只需要向工厂索要即可,初步实现了责任的分离。客户端只负责“消费”,工厂负责“生产”。生产和消费分离。
简单工厂模式的缺点:
● 缺点1:工厂类集中了所有产品的创造逻辑,形成一个无所不知的全能类,有人把它叫做上帝类。显然工厂类非常关键,不能出问题,一旦出问题,整个系统瘫痪。
● 缺点2:不符合OCP开闭原则,在进行系统扩展时,需要修改工厂类。
//抽象产品角色weapon
package com.sunsplanter.factory;
//抽象类无法被创建对象,无法实例化,是用来被子类继承的
//Tank和Weapon是is-a的关系
//且基本功能在不断变化(开炮/投弹),因此用抽象类
public abstract class Weapon {
/**
* 所有的武器都有攻击行为
*/
public abstract void attack();
}
//具体产品角色tank/Fighter
package com.sunsplanter.factory;
public class Tank extends Weapon{
@Override
public void attack() {
System.out.println("坦克开炮!");
}
}
```java
package com.sunsplanter.factory;
public class Fighter extends Weapon{
@Override
public void attack() {
System.out.println("战斗机投下原子弹!");
}
}
//工厂类角色
package com.sunsplanter.factory;
public class WeaponFactory {
/**
* 根据不同的武器类型生产武器
* @param weaponType 武器类型
* @return 武器对象
*/
public static Weapon get(String weaponType){
if (weaponType == null || weaponType.trim().length() == 0) {
return null;
}
Weapon weapon = null;
if ("TANK".equals(weaponType)) {
weapon = new Tank();
} else if ("FIGHTER".equals(weaponType)) {
weapon = new Fighter();
} else {
throw new RuntimeException("不支持该武器!");
}
return weapon;
}
}
package com.powernode.factory;
public class Client {
public static void main(String[] args) {
Weapon weapon1 = WeaponFactory.get("TANK");
weapon1.attack();
Weapon weapon2 = WeaponFactory.get("FIGHTER");
weapon2.attack();
}
}
工厂方法模式
简单工厂违背了开闭原则,即每次扩展系统时,都要修改工厂类…工厂方法模式的将简单工厂模式的工厂类解耦为抽象工厂+具体工厂,每次扩展系统只要实现一次抽象工厂的接口就可以,不必修改原有程序.
工厂方法模式的角色包括:
● 抽象工厂角色
● 具体工厂角色
● 抽象产品角色
● 具体产品角色
工厂方法模式的优点:
● 一个调用者想创建一个对象,只要知道其名称就可以了。
● 扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。
● 屏蔽产品的具体实现,调用者只关心产品的接口。
工厂方法模式的缺点:
● 每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。
可以看到简单工厂和工厂方法的区别只在于:简单工厂模式的工厂类解耦为抽象工厂+具体工厂,他们的抽象产品角色和具体产品角色仍然是相同的.
//抽象产品角色
package com.sunsplanter.factory;
public abstract class Weapon {
/**
* 所有武器都有攻击行为
*/
public abstract void attack();
}
//具体产品角色tank/Fighter
package com.sunsplanter.factory;
public class Tank extends Weapon{
@Override
public void attack() {
System.out.println("坦克开炮!");
}
}
```java
package com.sunsplanter.factory;
public class Fighter extends Weapon{
@Override
public void attack() {
System.out.println("战斗机投下原子弹!");
}
}
//抽象工厂角色(武器工厂接口)
package com.sunsplanter.factory;
public interface WeaponFactory {
Weapon get();
}
//具体工厂角色
package com.sunsplanter.factory;
public class TankFactory implements WeaponFactory{
@Override
public Weapon get() {
return new Tank();
}
}
//具体工厂角色
package com.sunsplanter.factory;
public class FighterFactory implements WeaponFactory{
@Override
public Weapon get() {
return new Fighter();
}
}
package com.sunsplanter;
public class Client {
public static void main(String[] args) {
TankFactory tankFactory = new TankFactory();
//Weapon类型的gun
Tank tank = tankFactory.get();
tank.attack();
}
}
如果想扩展一个新的产品,只要新增一个产品类,再新增一个该产品对应的工厂即可,例如新增:匕首
//新增一个具体产品角色
package com.sunsplanter;
public class Dagger extends Weapon{
@Override
public void attack() {
System.out.println("砍丫的!");
}
}
//新增一个具体工厂角色
package com.sunsplanter;
public class DaggerFactory implements WeaponFactory{
@Override
public Weapon get() {
return new Dagger();
}
}
抽象工厂模式
在工厂方法模式上再次进化,允许存在多个产品系列/工厂系列.
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!