[Design Patterns] 设计模式(二) 工厂方法模式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/FightFightFight/article/details/82086001

概述

工厂方法模式(Factory Method Pattern),是工厂模式之一,用于管理对象的创建,并将这些行为封装在子类中,从而完成父类代码和子类对象创建代码的解耦。它定义了一个创建对象的接口(Creator),但由子类决定要实例化的是哪一个,即将类的实例化推迟到了子类。

使用场景

工厂模式最重要的用途就是解耦,通过抽象的工厂方法将子类的创建和父类进行解耦,因此适用于复杂对象的创建。

组成元素

  • 抽象创建者(Creator):抽象的创建者类,定义了一个抽象的工厂方法,以便让子类实现该方法制造产品;
  • 抽象产品类:由创建者创建的具体的产品类;
  • 具体创建工厂:最终用来创建对象的工厂;
  • 具体产品类:最终要创建的对象;

UML类图

这里写图片描述

示例

现有一个电脑专卖店负责组装并售卖电脑,当收到一个订单时,会按照组装电脑—>发货—>派送—>签收的流程完成交易,现在就以它为例,看看如何通过工厂方法模式进行实现。

原始方式

电脑实体类如下:

package com.jyq.factory2;

public class Computer {

    private String mName;

    public Computer(String mName) {
        this.mName = mName;
    }
    public String toString() {
        return mName;
    }
}

电脑专卖店如下:

package com.jyq.factory2;

public class ComputerShop {

    public void sellComputer(String type, boolean isPro){
        Computer computer = createComputer(type, isPro);
        transport();
        delivery();
        signed();
    }
    public void transport() {
        System.out.println("运输中...");
    }

    public void delivery() {
        System.out.println("派件中...");
    }

    public void signed() {
        System.out.println("已签收...");
    }

    /**
     * 组装电脑
     * @param type 电脑品牌
     * @param isPro 是否高配
     * @return 
     */
    public Computer createComputer(String type,boolean isPro) {
        Computer computer = null;
        if ("lenovo".equals(type)) {
            if (isPro) {
                computer = new Computer("Lenovo High Configuration:1000G+16G+i7");
            } else {
                computer = new Computer("Lenovo Low Configuration:500G+8G+i5");
            }
        } else {
            if (isPro) {
                computer = new Computer("Dell High Configuration:1000G+16G+i7");
            } else {
                computer = new Computer("Dell Low Configuration:500G+8G+i5");
            }
        }
        System.out.println("组装成功:"+computer.toString());
        return computer;
    }

}

这是最原始的方式实现这个功能。然而,随着电脑品牌的不断增多,我们就必须对createComputer()方法进行不断修改,这显然违背了对修改关闭,对扩展开放的规则,显然是行不通的,于是呢,就出现了下面这种方式。

简单工厂方式

在这个方法中,我们定义一个电脑工厂类,并将组装电脑的任务交给电脑工厂,电脑专卖店只负责从电脑工厂拿货即可,修改下电脑专卖店

package com.jyq.factory2;

public class ComputerShop {

    private ComputerFactory cf;
    public ComputerShop(ComputerFactory cf) {
        this.cf = cf;
    }

    public void sellComputer(String type, boolean isPro){
        Computer computer = cf.createComputer(type, isPro);
        transport();
        delivery();
        signed();
    }
    public void transport() {
        System.out.println("运输中...");
    }

    public void delivery() {
        System.out.println("派件中...");
    }

    public void signed() {
        System.out.println("已签收...");
    }
}

创建一个电脑工厂:

package com.jyq.factory2;

public class ComputerFactory {

    /**
     * @param type 电脑类型
     * @param isPro 是否高配
     * @return
     */
    public Computer createComputer(String type,boolean isPro) {
        Computer computer = null;
        if ("lenovo".equals(type)) {
            if (isPro) {
                computer = new LenovoComputer("Lenovo High Configuration:1000G+16G+i7");
            } else {
                computer = new LenovoComputer("Lenovo Low Configuration:500G+8G+i5");
            }
        } else {
            if (isPro) {
                computer = new DellComputer("Dell High Configuration:1000G+16G+i7");
            } else {
                computer = new DellComputer("Dell Low Configuration:500G+8G+i5");
            }
        }
        return computer;
    }
}

这种方式相比于原始方式而言,将实例化工作放在了一个简单的工厂中完成,因此称为简单工厂方式,但是,它并不是一个设计模式,而是一种编程习惯。

随着用户的增加,对电脑品牌的需求也不断加多,因此,电脑商店需要从不同的电脑工厂进货,使用”简单工厂方式”似乎并不能很好的满足要求,这时主角”工厂方法模式”出现。

工厂方法模式

每个电脑品牌都有一个工厂,但他们都基于一个统一的接口,这些就是”抽象创建者”和”具体创建者”:

package com.jyq.factory2;

public abstract class ComputerFactory {

    public abstract <T extends Computer> T createComputer(Class<T> clz);
}

// 用于生产联想牌电脑工厂
package com.jyq.factory2;

public class LenovoComputerFactory extends ComputerFactory {

    @Override
    public <T extends Computer> T createComputer(Class<T> clz) {
        // TODO Auto-generated method stub
        Computer computer = null;
        try {
            System.out.println("联想工厂开始组装...");
            computer = (Computer) Class.forName(clz.getName()).newInstance();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            System.out.println(e.toString());
        }
        return (T) computer;
    }

}

//用于生产Dell品牌电脑工厂
package com.jyq.factory2;

public class DellComputerFactory extends ComputerFactory {

    @Override
    public <T extends Computer> T createComputer(Class<T> clz) {
        // TODO Auto-generated method stub
        Computer computer = null;
        try {
            System.out.println("戴尔工厂开始组装...");
            computer = (Computer) Class.forName(clz.getName()).newInstance();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return (T) computer;
    }
}

在这三个工厂中,ComputerFactory定义了一个接口createComputer(),不同工厂的生产步骤也许有所不同,因此它是被abstract关键字修饰,所有工厂都可以自己决定如何生产。

这种设计模式就是工厂方法模式,它让子类来决定如何创建对象,以及创建什么对象。

我们补齐剩余代码:


//电脑实体类
package com.jyq.factory2;

public class Computer {

}

package com.jyq.factory2;

public class LenovoComputer extends Computer {

    public LenovoComputer() {
        System.out.println("喜提联想电脑一台...");
    }

}

package com.jyq.factory2;

public class DellComputer extends Computer {

    public DellComputer() {
        System.out.println("喜提Dell一台...");
    }

}

//电脑专卖店

package com.jyq.factory2;

public class ComputerShop {

    private ComputerFactory cf;
    private Class<? extends Computer> clz;
    public ComputerShop(ComputerFactory cf,Class<? extends Computer> clz) {
        this.cf = cf;
        this.clz = clz;
    }

    public void sellComputer(){
        cf.createComputer(clz);
        transport();
        delivery();
        signed();
    }
    public void transport() {
        System.out.println("运输中...");
    }

    public void delivery() {
        System.out.println("派件中...");
    }

    public void signed() {
        System.out.println("已签收...");
    }
}

//客户开始订购电脑
package com.jyq.factory2;

public class DemoFactory {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        ComputerFactory lcf = new LenovoComputerFactory();
        ComputerShop shop = new ComputerShop(lcf,LenovoComputer.class);
        shop.sellComputer();
    }
}

该例UML类图如下:

这里写图片描述

猜你喜欢

转载自blog.csdn.net/FightFightFight/article/details/82086001
今日推荐