* 24种设计模式——工厂模式

来源:互联网 发布:北京淘宝客服简历模板 编辑:程序博客网 时间:2024/06/05 15:06

核心:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。

一、女娲造人的故事

1. 人类总称

public interface Human {public void getColor();public void talk();}
2. 黑色人种

public class BlackHuman implements Human{public void getColor() {System.out.println("黑种人的皮肤是黑色的!");}public void talk() {System.out.println("黑人会说话,一般人听不懂!");}}
3. 黄色人种

public class YellowHuman implements Human{public void getColor() {System.out.println("黄种人的皮肤是黄色的!");}public void talk() {System.out.println("黄程人说话,一般是双字节的!");}}
4. 白色人种

public class WhiteHuman implements Human{public void getColor() {System.out.println("白色人种的皮肤是白色的!");}public void talk() {System.out.println("白色人会话说,一般是单字节的!");}}
5. 抽象人类工厂类

public abstract class AbstractHumanFactory {public abstract <T extends Human> T createHuman(Class<T> c);}
6.  人类创建工厂

public class HumanFactory extends AbstractHumanFactory{public <T extends Human> T createHuman(Class<T> c) {//return c.newInstance();Human human = null;try {human = (T)Class.forName(c.getName()).newInstance();} catch (Exception e) {System.out.println("人种生成错误");}return (T) human;}}
7. 女娲类

public class NvWa {public static void main(String[] args) {AbstractHumanFactory YinYangLu = new HumanFactory();Human whiteHuman = YinYangLu.createHuman(WhiteHuman.class);whiteHuman.getColor();whiteHuman.talk();BlackHuman blackHuman = YinYangLu.createHuman(BlackHuman.class);blackHuman.getColor();blackHuman.talk();YellowHuman yellowHuman = YinYangLu.createHuman(YellowHuman.class);yellowHuman.getColor();yellowHuman.talk();}}
二、工厂方法模式的定义

定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。

1. 抽象产品类

public abstract class Product {//产品类的公共方法public void method1() {//业务处理}//抽象方法public abstract void method2();}
2. 具体产品类,可有多个,都继承于抽象产品类

public class ConcreteProduct1 extends Product{public void method2() {//业务处理}}
public class ConcreteProduct2 extends Product{public void method2() {//业务处理}}
3. 抽象工厂类,负责定义产品对象的产生

public abstract class Creator {//创建一个产品对象,其输入参数类型可以自行设置,通常为String、Enum、Class等,当然也可以为空public abstract <T extends Product> T createProduct(Class<T> c);}
4. 具体工厂类
public class ConcreteCreator extends Creator{public <T extends Product> T createProduct(Class<T> c) {Product product = null;try {product = (Product) Class.forName(c.getName()).newInstance();} catch (Exception e) {//异常处理}return (T) product;}}
5. 场景类

public class Client {public static void main(String[] args) {Creator creator = new ConcreteCreator();Product product = creator.createProduct(ConcreteProduct1.class);//业务处理}}

三、工厂方法模式的优点

1. 一个调用者需要一个具体的产品对象,只要知道这个产品的类名(或约束字符串)就可以了,不用知道创建对象的艰辛过程,降低模块间的耦合。

2. 扩展性好,要加一个棕色人种,只用增加一个BrownHuman类。

3. 屏蔽产品类,调用者只用关心产品的接口,只要接口不变,系统 中的上层模块就不要发生变化,因为产品类的实例化是由工厂类负责的,一个产品对象具体由哪个产品生成是由工厂类决定的。在开发中,如果使用JDBC连接数据库,数据库从MySQL切换到Oracle,需要改动的地方就是切换一下驱动名称(前提是SQL语句是标准语句),其他都不用改,这是工厂方法模式的一个直接案例。

4. 符合迪米特法则:高层模块只需要知道产品的抽象类,其他的实现类都不用关心,不需要的就不要去交流。

    符合依赖倒置原则:只依赖产品类的抽象;

    符合里氏替换原则:使用产品子类替换产品父类也可以。

四、工厂方法的使用场景

1. 工厂方法模式是new一个对象的替代品,所以在所有生成对象的地方都可以使用,但是需要慎重地考虑是否要增加一个工厂类进行管理,增加代码的复杂度。

2. 需要灵活的、可扩展的框架时,例如需要设计一个连接邮件服务器的框架,有三种网络协议可选择:POP3、IMAP、HTTP,我们就可以把这三种连接方法作为产品类,定义一个接口如IConnectMail,然后定义对邮件的操作方法,用不同的方法实现 三个具体的产品类(也就是连接方式)再定义一个工厂方法,按照不同的传入条件,选择不同的连接方式。

五、工厂方法模式的扩展

1. 缩小为简单工厂模式

在类图中去掉AbstractHumanFactory,同时把HumanFactory中的createHuman方法修改为static静态方法,简化了工厂类的创建过程。

而场景类中只用调用下列代码,就可产生一个实例类:

Human whiteHuman = HumanFactory.createHuman(WhiteHuman.class);

缺点:工厂类的扩展比较,不符合开闭原则。

2. 升级为多个工厂类

用于对多种产品(有各自特性或初始化方法)的情况下,可能不适合用同一个工厂,这时可用多个工厂,各工厂各自的产品。

每个产品都对应一个创建类,好处是创建类的职责清晰,结构简单,但给可扩展性和可维护性带来一定影响。比如,如果要扩展一个产品类,就需要建立一个相应的工厂类,这样就增加了扩展的难度。
在复杂的应用中一般采用多工厂方法,然后再增加一个协调类,避免调用者与各个子工厂交流,协调类的作用是封闭子工厂类,对高层模块提供统一的访问接口。

抽象工厂类:

public abstract class AbstractHumanFactory {public abstract Human createHuman();}

黑种人工厂类:

public class BlackHumanFactory extends AbstractHumanFactory{public Human createHuman() {return new BlackHuman();}}
白种人工厂类:

public class WhiteHumanFactory extends AbstractHumanFactory{public Human createHuman() {return new WhiteHuman();}}
黄种人工厂类:

public class YellowHumanFactory extends AbstractHumanFactory{public Human createHuman() {return new YellowHuman();}}
场景类:

public class NvWa {public static void main(String[] args) {Human whiteHuman = (new WhiteHumanFactory()).createHuman();whiteHuman.getColor();whiteHuman.talk();Human blackHuman = (new BlackHumanFactory()).createHuman();blackHuman.getColor();blackHuman.talk();Human yellowHuman = (new YellowHumanFactory()).createHuman();yellowHuman.getColor();yellowHuman.talk();}}

3. 单例类

需要单例的类

public class Singleton {private Singleton(){}public void doSomething() {System.out.println("111");}}
单例Factory方法

public class SingletonFactory {private static Singleton singleton;static{try {Class cl = Class.forName(Singleton.class.getName());Constructor constructor = cl.getDeclaredConstructor();constructor.setAccessible(true);singleton = (Singleton)constructor.newInstance();} catch (Exception e) {//异常处理}}public static Singleton getSingleton(){return singleton;}}
4. 延迟初始化

一个对象初始化后,并不立刻释放,工厂类保持其初始状态,等待再次被使用。

public class ProductFactory {private static final Map<String,Product> prMap = new HashMap<String,Product>();public static synchronized Product createProduct(String type) {Product product = null;if(prMap.containsKey(type)){return prMap.get(type);}else{if(type.equals("Product1")){product = new ConcreteProduct1();}else if(type.equals("Product2")){product = new ConcreteProduct2();}prMap.put(type, product);}return product;}}

原创粉丝点击