-
设计模式:一种可以被重复利用的解决方案。
-
GoF(Gang of Four),中文名——四人组。
-
《Design Patterns: Elements of Reusable Object-Oriented Software》(即《设计模式》一书),1995年由 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 合著。这几位作者常被称为"四人组(Gang of Four)"。
-
该书中描述了23种设计模式。我们平常所说的设计模式就是指这23种设计模式。
-
不过除了GoF23种设计模式之外,还有其它的设计模式,比如:JavaEE的设计模式(DAO模式、MVC模式等)。
-
GoF23种设计模式可分为三大类:
- 创建型(5个):解决对象创建问题。
- 单例模式
- 工厂方法模式
- 抽象工厂模式
- 建造者模式
- 原型模式
- 结构型(7个):一些类或对象组合在一起的经典结构。
- 代理模式
- 装饰模式
- 适配器模式
- 组合模式
- 享元模式
- 外观模式
- 桥接模式
- 行为型(11个):解决类或对象之间的交互问题。
- 策略模式
- 模板方法模式
- 责任链模式
- 观察者模式
- 迭代子模式
- 命令模式
- 备忘录模式
- 状态模式
- 访问者模式
- 中介者模式
- 解释器模式
- 创建型(5个):解决对象创建问题。
-
工厂模式是解决对象创建问题的,所以工厂模式属于创建型设计模式。Spring框架底层使用了大量的工厂模式。
1 工厂模式的三种形态
工厂模式通常有三种形态:
- 第一种:简单工厂模式(Simple Factory):不属于23种设计模式之一。简单工厂模式又叫做:静态 工厂方法模式。简单工厂模式是工厂方法模式的一种特殊实现。
- 第二种:工厂方法模式(Factory Method):是23种设计模式之一。
- 第三种:抽象工厂模式(Abstract Factory):是23种设计模式之一
2 简单工厂模式
设计模式之:简单工厂模式 Simple Factory Pattern
-
简单工厂模式是工厂方法模式的一种特殊实现,又被称为:静态工厂方法模式。
-
简单工厂模式中的角色:
- 抽象产品角色
- 具体产品角色
- 工厂类角色
简单工厂模式的代码如下:抽象产品角色:
package com.powernode.simple.factory; /** * 抽象产品角色 */ public abstract class Weapon { /** * 所有的武器都可以攻击 */ public abstract void attack(); }
具体产品角色:
package com.powernode.simple.factory; /** * 具体产品角色 */ public class Tank extends Weapon{ @Override public void attack() { System.out.println("坦克开炮!!"); } }
package com.powernode.simple.factory; /** * 具体产品角色 */ public class Fighter extends Weapon{ @Override public void attack() { System.out.println("战斗机射击"); } }
package com.powernode.simple.factory; /** * 具体产品角色 */ public class Dagger extends Weapon{ @Override public void attack() { System.out.println("砍"); } }
工厂类角色:
package com.powernode.simple.factory; /** * 工厂类角色 */ public class WeaponFactory { /** * 静态方法。获取什么产品,看传什么参数 * 简单工厂模式中有一个静态方法,所以被称为:静态工厂方法模式 * @param weaponType * @return */ public static Weapon get(String weaponType){ if ("TANK".equals(weaponType)) { return new Tank(); } else if ("FIGHTER".equals(weaponType)){ return new Fighter(); } else if ("DAGGER".equals(weaponType)){ return new Dagger(); } else { throw new RuntimeException("不支持该武器的生产"); } } }
测试程序(客户端程序):
package com.powernode.simple.factory; /** * 客户端程序 */ public class Test { public static void main(String[] args) { // 对于客户端来说,坦克的生产细节,不需要关心,只需要向工厂索要即可。 // 简单工厂模式达到了什么呢?职责分离。客户端不需要关心产品的生产细节。 // 客户端只负责消费。工厂类负责生产。一个负责生产,一个负责消费。生产者和消费者分离了。这就是简单工厂模式的作用。 // 需要坦克 Weapon tank = WeaponFactory.get("TANK"); tank.attack(); // 需要匕首 Weapon dagger = WeaponFactory.get("DAGGER"); dagger.attack(); // 需要战斗机 Weapon fighter = WeaponFactory.get("FIGHTER"); fighter.attack(); } }
-
简单工厂模式的优点?
客户端程序不需要关心对象的创建细节,需要哪个对象时,只需要向工厂索要即可,初步实现了责任的分离。
客户端只负责“消费”,工厂负责“生产”。生产和消费分离。 -
简单工厂模式的缺点?
缺点一:假设现在需要扩展一个新的产品,WeaponFactory工厂类的代码是需要修改的,显然违背了OCP原则。不符合OCP开闭原则,在进行系统扩展时,需要修改工厂类。
缺点二:工厂类集中了所有产品的创造逻辑,形成一个无所不知的全能类,有人把它叫做上帝类。显然工厂类非常关键,不能出问题,一旦出问题,整个系统瘫痪。
Spring中的BeanFactory就使用了简单工厂模式。
3 工厂方法模式
工厂方法模式既保留了简单工厂模式的优点,同时又解决了简单工厂模式的缺点。
-
工厂方法模式可以解决简单工厂模式当中的OCP问题。
怎么解决的?一个工厂对应生产一种产品。
这样工厂就不是全能类了,不是上帝类了。
另外,也可以符合OCP原则。 -
工厂方法模式中的角色:
- 抽象产品角色
- 具体产品角色
- 抽象工厂角色
- 具体工厂角色
简单工厂模式的代码如下:抽象产品角色:
package com.powernode.factory.method; /** * 抽象产品角色 **/ abstract public class Weapon { public abstract void attack(); }
具体产品角色:
package com.powernode.factory.method; /** * 具体产品角色 **/ public class Dagger extends Weapon{ @Override public void attack() { System.out.println("砍"); } }
package com.powernode.factory.method; /** * 具体产品角色 **/ public class Gun extends Weapon{ @Override public void attack() { System.out.println("开枪射击!!!"); } }
抽象工厂角色:
package com.powernode.factory.method; /** * 抽象工厂角色 **/ abstract public class WeaponFactory { /** * 这个方法不是静态的。是实例方法。 * @return */ public abstract Weapon get(); }
具体工厂角色:
package com.powernode.factory.method; /** * 具体工厂角色 **/ public class DaggerFactory extends WeaponFactory{ @Override public Weapon get() { return new Dagger(); } }
package com.powernode.factory.method; /** * 具体工厂角色 **/ public class GunFactory extends WeaponFactory{ @Override public Weapon get() { return new Gun(); } }
客户端程序:
package com.powernode.factory.method; /** * 客户端程序 **/ public class Test { public static void main(String[] args) { WeaponFactory weaponFactory = new DaggerFactory(); Weapon dagger = weaponFactory.get(); dagger.attack(); WeaponFactory weaponFactory1 = new GunFactory(); Weapon gun = weaponFactory1.get(); gun.attack(); } }
-
工厂方法模式的优点:
当你扩展一个产品的时候,符合OCP原则,因为只需要添加两个类,一个类是具体产品类,一个类是具体工厂类。都是添加类,没有修改之前的代码,所以符合OCP。- 一个调用者想创建一个对象,只要知道其名称就可以了。
- 扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。
- 屏蔽产品的具体实现,调用者只关心产品的接口。
-
工厂方法模式的缺点:
每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,
在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。
4 抽象工厂模式(了解)
抽象工厂模式相对于工厂方法模式来说,就是工厂方法模式是针对一个产品系列的,而抽象工厂模式是针对多个产品系列的,即工厂方法模式是一个产品系列一个工厂类,而抽象工厂模式是多个产品系列一个工厂类。
抽象工厂模式特点:抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。它有多个抽象产品类,每个抽象产品类可以派生出多个具体产品类,一个抽象工厂类,可以派生出多个具体工厂类,每个具体工厂类可以创建多个具体产品类的实例。每一个模式都是针对一定问题的解决方案,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式针对的是多个产品等级结果。
抽象工厂中包含4个角色:
- 抽象工厂角色
- 具体工厂角色
- 抽象产品角色
- 具体产品角色
抽象工厂模式的类图如下
抽象工厂模式的优缺点:
- 优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
- 缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在AbstractFactory里加代码,又要在具体的里面加代码。