1.Java设计模式-工厂模式

1.简单工厂模式(Factory Method

常用的工厂模式是静态工厂模式,利用static修饰方法,作为一种类似于常见的工具类Utils等辅助效果,一般情况下工厂类不需要实例化。

//1.定义一个基类接口
public interface Video {
    //定义一个生产视频的方法
    public void produce();
}
//2.定义实现类
public class JavaVideo implements Video {
    @Override
    public void produce() {
        System.out.println("生产java视频");
    }
}
public class PythonVideo implements Video {
    @Override
    public void produce() {
        System.out.println("生产python视频的方法");
    }
}
//3.定义视频工厂
public class VideoFactory {
    public static Video getVideo(String type) {
        if("java".equalsIgnoreCase(type)) {
            return new JavaVideo();
        }else if("python".equalsIgnoreCase(type)) {
            return new PythonVideo();
        }else {
            return null;
        }    
    }
}
//4.测试类
public class Test {
    public static void main(String[] args) {
        Video video = VideoFactory.getVideo("java");
        if(video==null) {
            return;
        }
        video.produce();
    }
}
View Code

工厂模式缺点:

    工厂类的职责相对过重,增加新的产品需要修改工厂类的判断逻辑,违反开闭原则。但上述工厂类模式随着生产课程种类原来越多,工厂里的方法要不断修改,不符合开闭原则。

改进:

1.1.  利用反射弥补扩展性,重新定义VideoFactory内的getVideo方法。

//修改工厂类
public class VideoFactory01 {
    public static Video getVideo(Class<?> c) {
        Video video=null;
        try {
            video=(Video) Class.forName(c.getName()).newInstance();
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return video;
    }
}
//测试类
public class Test1 {
    public static void main(String[] args) {
        Video video = VideoFactory01.getVideo(PythonVideo.class);
        video.produce();
    }
View Code

1.2.工厂类只定义规范(接口),创建不同的实例只需要不同的工厂类实现统一的工厂接口即可。这样可以放VideoFactory这个超类代码与子类创建对象的代码解耦。(工厂模式)

//视频工厂只提供规范,具体创建何种实例由具体的工厂实现类来决定
public interface VideoFactory02 {
    public Video getVideo();
}
//具体的实现
public class JavaVideoFactory02 implements VideoFactory02 {
    @Override
    public Video getVideo() {
        return new JavaVideo();
    }
}
public class PythonVideoFactory02 implements VideoFactory02 {
    @Override
    public Video getVideo() {
        // TODO Auto-generated method stub
        return new PythonVideo();
    }
}
//测试类
public class Test2 {
    /**
     * 现在创建什么类型的视频是由VideoFactory的子类决定的,VideoFactory只定义规范,契约
     * @param args
     */
    public static void main(String[] args) {
        VideoFactory02 factory=new JavaVideoFactory02();
        Video video= factory.getVideo();
        video.produce();
    }
}
View Code

     从扩展性的角度来看,现在如果要添加一门前端课程,只需要创建FeVideoFactory实现VideoFactory接口就可以了,不需要修改VideoFactory的代码实现。符合开闭原则。且FeVideo,JavaVideo,PythonVideo处于同一产品等级,工厂模式就是方便解决同一产品等级创建实例的。

2.工厂模式深入——体现产品等级概念

      举个栗子:假设我们想要找电脑组装人员DIY组装一台电脑。我们希望自己选择CPU、主板、内存、电源、显卡、电源等。由于内容较多,我们就拿CPU和主板来说事。

       在选择CPU的时候,主要的参数有CPU品牌,型号,针脚数量,主频等,只有这些都确定下来,我们才能确定具体的CPU;

       主板也一样,主板的主要参数有品牌,芯片组,总线频率等,只有这些确定下来,我们才能确定具体主板;

       且在选择的时候我们还需要考虑到CPU和主板的兼容性,比如说Intel的CPU与AMD的主板就不兼容,因为Intel的CPU的针脚数目与AMD主板的CPU插孔数量不一致,根本无法插入。所以装机方案需要整体考虑,里边的不同模块之间是有关联的。

      对于装机工程师来说,他只知道组装一台电脑需要响应的配件,而具体的配件选择还是需要由客户决定。对于不同的客户做出的选择不同,他需要根据客户的选择去获取配件,然后为该客户完成组装。

      使用工厂模式的解决方案:

     对于装机工程师来说,他只知道组装电脑需要CPU和主板,而两者具体选择什么品牌,型号他确定不了,需要客户去选择,客户选择好后他负责去相应的工厂里边获取这两种配件,然后组装。

    2.1.Cpu接口与具体实现

 

//Cpu接口
package com.itheima.pattern.entity;
public interface CPU {
    //CPU具有计算功能
    public void calculate();
}
//Cpu具体实现Intel,可供客户选择
package com.itheima.pattern.entity;

public class IntelCpu implements CPU { 
    private int pins;
    public IntelCpu(int pins) {
        this.pins = pins;
    }

    @Override
    public void calculate() {
        System.out.println("Intel Cpu的针脚数:"+pins);
    }
}
//Cpu具体实现Amd,可供客户选择
package com.itheima.pattern.entity;

public class AmdCpu implements CPU {
    
    private int pins;
    public AmdCpu(int pins) {
        this.pins = pins;
    }
    @Override
    public void calculate() {
        System.out.println("Amd Cpu针脚数:"+pins);
    }
}
View Code

 

   2.2.主板接口与具体实现

//主板接口
package com.itheima.pattern.entity;

public interface Mainboard {
    //主板上安装Cpu
    public void installCpu();
}

//主板具体实现Intel,可供客户选择
package com.itheima.pattern.entity;

public class IntelMainboard implements Mainboard {
    /**
     * cpu插槽孔数
     */
    private int cpuHolds;    
    public IntelMainboard(int cpuHolds) {
        this.cpuHolds = cpuHolds;
    }

    @Override
    public void installCpu() {
        System.out.println("Intel主板CPU插槽孔数是:"+cpuHolds);
    }
}

//主板具体实现Amd,可供客户选择
package com.itheima.pattern.entity;

public class AmdMainboard implements Mainboard {
    private int cpuHolds;
    public AmdMainboard(int cpuHolds) {
        this.cpuHolds = cpuHolds;
    }
    @Override
    public void installCpu() {
        System.out.println("Amd 主板Cpu插槽孔数:"+cpuHolds);
    }
}
View Code

   2.3.创建Cpu工厂

package com.itheima.pattern.factory;

import com.itheima.pattern.entity.AmdCpu;
import com.itheima.pattern.entity.CPU;
import com.itheima.pattern.entity.IntelCpu;

public class CpuFactory {
    
    public static CPU createCpu(int type) {
        CPU cpu=null;
        if(type==1) {
            cpu=new IntelCpu(755);    
        }else if(type==2) {
            cpu=new AmdCpu(938);    
        }else {
            return null;
        }
        return cpu;
    }
}
View Code

  2.4.创建主板工厂

package com.itheima.pattern.factory;

import com.itheima.pattern.entity.AmdMainboard;
import com.itheima.pattern.entity.IntelMainboard;
import com.itheima.pattern.entity.Mainboard;

public class MainboardFactory {
    public static Mainboard createMainboard(int type) {
        if(type==1) {
            return new IntelMainboard(755);
        }else if(type==2) {
            return new AmdMainboard(938);
        }else {
            return null;
        }
    }
}
View Code

  2.5.电脑组装工程师(工厂调用者)

package com.itheima.pattern.computerEngineer;

import com.itheima.pattern.entity.CPU;
import com.itheima.pattern.entity.Mainboard;
import com.itheima.pattern.factory.CpuFactory;
import com.itheima.pattern.factory.MainboardFactory;

public class ComputerEngineer {
    //装机需要Cpu
    private CPU cpu;
    //装机需要主板
    private Mainboard mainboard;
    //组装电脑
    public void makeComputer(int cpuType,int boardType) {
        cpu=CpuFactory.createCpu(cpuType);
        mainboard=MainboardFactory.createMainboard(boardType);
        cpu.calculate();
        mainboard.installCpu();
        System.out.println("电脑组装完成,可以使用");
    }
}
View Code

  2.6.客户(使用者)

package com.itheima.pattern.client;

import com.itheima.pattern.computerEngineer.ComputerEngineer;

public class Client {
    public static void main(String[] args) {
        ComputerEngineer computerEngineer = new ComputerEngineer();
        computerEngineer.makeComputer(1, 1);
    }
}
View Code

  2.7.程序运行结果

上边的实现是采用简单工厂模式实现的,但有个问题没有解决,就是Cpu与主板之间的兼容关系没有解决,实际上Cpu与主板之间时候有关系的,需要相互匹配。而上边的实现并没有维护这种关系。因此当客户选择makeComputer(1, 2)时,将出现无法组装的情况。该如何避免这种情况的发生?需要引入抽象工厂模式。见下一节。

 

 

posted @ 2018-12-20 21:28  逆天改梦  阅读(241)  评论(0编辑  收藏  举报