黑马程序员-Java _ 简单工厂设计模式(Plant Pattern)

--------- android培训java培训、期待与您交流!----------


一、所谓工厂,就是能把原材料造出很多对应产品的工具

   接下来我们以制作影片的例子来说明:

   动作片:actionMovie      

   爱情片:affectionalMovie  

   武侠片:swrodsmenMovie    

   代码是最好的老师,且看代码:


1、首先,定义一个影片的总称

package com.itheima.plantpattern;
/**
 * @author Administrator
 * 定义一个影片的总称,接口
 */
public interface Movie
{
    //首先定义什么是影片
    //影片主要是人在表演
    public void act();
}

2、然后定义具体的影片对象

(1)动作片:

package com.itheima.plantpattern;
/**
 * @author Administrator
 * 动作片:ActionMovie
 */
public class ActionMovie implements Movie
{
    public void act()
    {
        System.out.println("这是动作片:");
    }
}

(2)爱情片:

package com.itheima.plantpattern;
/**
 * @author Administrator
 * 爱情片:AffectionalMovie
 */
public class AffectionalMovie implements Movie {
    @Override
    public void act() {
        System.out.println("这是爱情片:");
    }
}

(3)武侠片:

package com.itheima.plantpattern;
/**
 * @author Administrator
 * 武侠片:SwrodsmenMovie
 */
public class SwrodsmenMovie implements Movie
{
    @Override
    public void act()
    {
        System.out.println("这是武侠片:");
    }
}


3、具体影片的媒体文件我们已经有了,接下我们就要定义一个加工厂该加工厂的目的就是把这些媒体文件制作成影片.

package com.itheima.plantpattern;
/**
 * @author Administrator
 * 定义一个能生产影片的制作工厂
 */
public class MovieFactory {
    //将媒体原文件放到工厂,影片就出来了,非常方便!
    public static Movie creatMovie(Class<? extends Movie> clazz){
        Movie movie = null;//定义一个影片类型。
        try
        {
            movie = (Movie)Class.forName(clazz.getName()).newInstance();
        } catch (InstantiationException e)
        {
            System.out.println("该影片媒体原文件有误,创建失败!");
        } catch (IllegalAccessException e)
        {
            System.out.println("如果该影片不能访问!");
        } catch (ClassNotFoundException e)
        {
            System.out.println("你指定的影片类型不存在!");
        }
        return movie;
    }
}
/*如果一个工厂只制作一种类型的影片,那么可以这样定义,不过还是没有上
面定义的方法那么好,因为用这种方法对象必须存在才行。而通过反射的方式
是在运行时才产生对象,更符合实际逻辑规则。当需要制作其他类型的影片时
不用再修改原代码,而只需要新建一种类型的影片再实现影片该具有的功能就
可以了。*/
class MovieFactory2
{
    public static Movie creatMovie()
    {
        return new AffectionalMovie();
    }
}


4、影片媒体的文件已经制作出来了,但如果工厂里没人,影片还是没法制作出来,所以还要找一个制片人。

package com.itheima.plantpattern;
/**
 * @author Administrator
 * 制片人: Producer
 */
public class Producer
{
    public static void main(String[] args)
    {
                                                                                                
        System.out.println("-----------------第一次制作动作片:");
        Movie actionMovie = MovieFactory.creatMovie(ActionMovie.class);
        actionMovie.act();
        System.out.println("-----------------第二次制作爱情片:");
        Movie affectionalMovie = MovieFactory.creatMovie(AffectionalMovie.class);
        affectionalMovie.act();
        System.out.println("-----------------第二次制作爱情片:");
        Movie swrodsmenMovie = MovieFactory.creatMovie(SwrodsmenMovie.class);
        swrodsmenMovie.act();
                                                                                                
        Movie movie = MovieFactory2.creatMovie();
        movie.act();
    }
}


二、对上面例子进行一些改进

   发现上面制作影片的流程有点复杂,每次制作影片前,要把具体的媒体文件放进工厂才能生成对应的影片。如果能实现把媒体文件,不管它是属于动作片,还是爱情片,或者武侠片,只要放进工厂,由工厂随机制作出动作片,爱情片或者武侠片,这样就方便多了。

1、首先,定义一个影片的总称.

package com.itheima.plantpattern;
/**
 * @author Administrator
 * 定义一个影片的总称,接口
 */
public interface Movie
{
    //首先定义什么是影片
    //影片主要是人在表演
    public void act();
}


2、然后定义具体的影片对象

(1)动作片:

package com.itheima.plantpattern;
/**
 * @author Administrator
 * 动作片:ActionMovie
 */
public class ActionMovie implements Movie
{
    public void act()
    {
        System.out.println("这是动作片:");
    }
}

(2)爱情片:

package com.itheima.plantpattern;
/**
 * @author Administrator
 * 爱情片:AffectionalMovie
 */
public class AffectionalMovie implements Movie {
    @Override
    public void act() {
        System.out.println("这是爱情片:");
    }
}

(3)武侠片:

package com.itheima.plantpattern;
/**
 * @author Administrator
 * 武侠片:SwrodsmenMovie
 */
public class SwrodsmenMovie implements Movie
{
    @Override
    public void act()
    {
        System.out.println("这是武侠片:");
    }
}


3、定义一个影片制作工厂,该工厂有两个方法,一个方法是随机产生具体媒体文件,再将媒体文件传给工厂加工。


package com.itheima.plantpattern2;
import java.util.List;
import java.util.Random;
/**
 * @author Administrator
 * 定义一个能生产影片的制作工厂
 */
public class MovieFactory
{
    //将媒体原文件放到工厂,影片就出来了!
    public static Movie createMovie(Class<? extends Movie> clazz)
    {
        Movie movie = null;//定义一个影片类型。
        try
        {
            movie = (Movie)Class.forName(clazz.getName()).newInstance();
        }
        catch (InstantiationException e)
        {
            System.out.println("该影片媒体原文件有误,创建失败!");
        }
        catch (IllegalAccessException e)
        {
            System.out.println("如果该影片不能访问!");
        }
        catch (ClassNotFoundException e)
        {
            System.out.println("你指定的影片类型不存在!");
        }
        return movie;
    }
    @SuppressWarnings("all")
    public static Movie createMovie()
    {  
        //首先要获取影片接口的所有实现类,也就是多少种影片,本次测试只有3种
        List<Class> concreteMovieList = ClassUtils.getAllClassByInterface(Movie.class);
        //开始随机产生影片
        //创建一个新的随机数生成器。
        Random random = new Random();
        /*返回一个伪随机数,它是取自此随机数生成器序列的、在 0(包括)和
        指定值(不包括)之间均匀分布的 int 值。就是角标对应影片*/
        int rand = random.nextInt(concreteMovieList.size());   
        //然后将随机的产生的影片媒体文件传给媒体文件加工工厂,就是有参的方法。
        Movie movie = createMovie(concreteMovieList.get(rand));
                                                  
        return movie;
    }
}


4、因为制作影片时,并没有创建媒体文件,所以这里还需要定义一个方法,专门创建媒体文件。

package com.itheima.plantpattern2;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
@SuppressWarnings("all")
public class ClassUtils {
    //传递一个接口类型的参数,返回这个接口的所有实现类
    public static List<Class> getAllClassByInterface(Class c){
        List<Class> retClassList = new ArrayList<Class>();
        //如果是接口
        if(c.isInterface()){
            //获取当前的包名
            String packageName = c.getPackage().getName();
            try {
                //调用getClasses方法,以获得当前包下以及子包的所有类
                List<Class> allClass = getClasses(packageName);
                for (int i = 0; i < allClass.size(); i++) {
                    /*判定此Class对象c所表示的类或接口与指定的Class
                    参数allClass.get(i)所表示的类或接口是否相同,或是
                    否是其超类或超接口。*/
                    if (c.isAssignableFrom(allClass.get(i))) {
                        //如果此Class对象c与allClass.get(i)类不相等
                        if (!c.equals(allClass.get(i))) {
                            System.out.println(c.getName());
                            //就添加 ,也就是本身不加进去。
                            retClassList.add(allClass.get(i));
                        }
                    }
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return retClassList;
    }
                                      
    private static List<Class> getClasses(String packageName) throws IOException, ClassNotFoundException{
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        //replace(char oldChar, char newChar);
        String path = packageName.replace('.', '/');
        //查找给定包路径下的所有资源
        Enumeration<URL> resources = classLoader.getResources(path);
        //定义一个存放目的文件目录的集合
        List<File> dirs = new ArrayList<File>();
        //测试此枚举是否包含更多的元素。
        while (resources.hasMoreElements()) {
            //如果此资源至少还有一个可提供的元素,则返回此资源的下一个元素
            URL resource = resources.nextElement();
            //getFile():获取此URL的文件名。
            dirs.add(new File(resource.getFile()));
        }
        ArrayList<Class> classes = new ArrayList<Class>();
        for (File directory : dirs) {
            //调用findClasses方法,该方法返回一个List<Class>集合
            //addAll:添加指定集合的所有元素到本集合。
            classes.addAll(findClasses(directory, packageName));
        }
        return classes;
    }
    private static List<Class> findClasses(File directory,String packageName) throws ClassNotFoundException {
        //定义一个存储.class文件的集合
        List<Class> classes = new ArrayList<Class>();
        //如果此目录不存在
        if(!directory.exists()){
            return classes;
        }
        //返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。
        File[] files = directory.listFiles();
        //运用递归遍历目录中的所有文件
        for (File file : files) {
            //如果该文件是目录
            if (file.isDirectory()) {
                //断言,
                assert !file.getName().contains(".");
                //返回此函数,继续遍历下层目录
                classes.addAll(findClasses(file, packageName + "." + file.getName()));
            }
            //如果不是文件夹,并且以.class文件结尾
            else if (file.getName().endsWith(".class")) {
                System.out.println(file.getName());
                //那么就获取其.class文件,并把它存放到集合中。
                classes.add(Class.forName(packageName + '.' + file.getName().substring(0, file.getName().length() - 6)));
            }
        }
        //返回存储.class文件的集合对象
        return classes;
    }
}


5、最后还需要找影片制作人.

package com.itheima.plantpattern2;
/**
 * @author Administrator
 * 制片人: Producer
 */
public class Producer {
    public static void main(String[] args) {
                                   
        System.out.println("-----------------第一次制作动作片:");
        Movie actionMovie = MovieFactory.createMovie(ActionMovie.class);
        actionMovie.act();
        System.out.println("-----------------第二次制作爱情片:");
        Movie affectionalMovie = MovieFactory.createMovie(AffectionalMovie.class);
        affectionalMovie.act();
        System.out.println("-----------------第二次制作爱情片:");
        Movie swrodsmenMovie = MovieFactory.createMovie(SwrodsmenMovie.class);
        swrodsmenMovie.act();      
        //随机制作影片
        for (int i = 0; i < 100; i++) {
            System.out.println("----------------随机产生影片-----------"+i);
                                       
            Movie movie = MovieFactory.createMovie();
            movie.act();
        }
    }
}



--------- android培训java培训、期待与您交流!----------

你可能感兴趣的:(Pattern,Plant,简单工厂设计模式)