一.实验目的
(1)熟悉建模工具
(2)掌握简单工厂模式、工厂方法模式、抽象工厂模式,并进行设计应用。
二.实验内容
2.1简单工厂模式
简单工厂模式属于类的创新型模式,又叫静态工厂方法模式。是通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
工厂角色:这是简单工厂模式的核心,由它负责创建所有的类的内部逻辑。工厂类必须能够被外界调用,创建所需要的产品对象。
抽象产品角色:简单工厂模式所创建的所有对象的父类,可以是接口也可以是抽象类,负责描述所有实例所共有的公共接口。
具体产品角色:简单工厂所创建的具体实例对象,这些具体的产品往往都拥有共同的父类。
优点:工厂类包含必要的判断逻辑,能够根据外界给定的信息,决定创建哪个具体类的对象。用户在使用时可以直接根据工厂类去创建所需的实例,而无需了解这些对象是如何创建及如何组织的。有利于整个软件体系结构的优化。
缺点:由于工厂类集中了所有实例的创建逻辑,这就导致一旦工厂出了问题,所有的客户端都会受到牵连;而且由于简单工厂模式的产品是基于同一个抽象类或者接口,当产品的种类增加,工厂类就需要判断何时创建何种种类的产品,违背了单一职责,导致系统丧失灵活性和可维护性。并且简单工厂模式违背了“开放封闭原则”,当新增加一个产品的时候必须修改工厂类,相应的工厂类就需要重新编译一遍。另外,简单工厂模式的方法一般都是静态的,而静态工厂方法是无法让子类继承的,因此,简单工厂模式无法形成基于基类的继承树结构。
2.1.1题目及分析
使用简单工厂模式模拟女娲(Nvwa)造人(Person),如果传入参数M,则返回一个Man对象,如果传入参数W,则返回一个Woman对象,请实现该场景。现需要增加一个新的Robot类,如果传入参数R,则返回一个Robot对象。
建立一个名为People的接口,作为抽象产品角色;创建具体的产品角色:男人、女人、机器人来实现接口;建立一个工厂角色名为Nvwa, 如果传入参数M,则返回一个Man对象等。最后建立测试客户端。
2.1.2类图设计
2.1.3运行结果及部分代码
抽象产品角色:People接口
package Person;
public interface People {
public void makepeople();}
工厂角色:Nvwa类,如果传入参数M,则返回一个Man对象,如果传入参数W,则返回一个Woman对象,如果传入参数R,则返回一个Robot对象。
package Person;
public class Nvwa {
public static People getPeople(String arg){
People people=null;
if(arg.equalsIgnoreCase("M")){
people=new Man(); }
else if(arg.equalsIgnoreCase("W")){
people=new Woman();}
else if(arg.equalsIgnoreCase("R")){
people=new Robot();}
return people;}
}
具体产品角色:Man类及测试类
package Person;
public class Man implements People {
public void makepeople() {
System.out.println("女娲创造出了男人");}
}
package Person;
public class Test {
public static void main(String[] args) {
People p;
p=Nvwa.getPeople("M");
p.makepeople();}
}
2.2工厂方法模式
工厂方法模式定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
抽象工厂角色:是工厂方法模式的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口。
具体工厂角色:这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建产品对象。
抽象产品角色:工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。
具体产品角色:这个角色实现了抽象产品角色所定义的接口。某具体产品有专门的具体工厂创建,它们之间往往一一对应。
2.2.1题目及分析
海尔工厂(Haier)生产海尔空调(HaierAirCondition),美的工厂(Midea)生产美的空调(MideaAirCondition) 。使用工厂方法模式描述该场景,绘制类图并编程实现。
建立抽象工厂角色为空调工厂Airfactory并创建函数produceAir();建立两个具体工厂角色分别为Haierfactory和Mideafactory用来实现接口;建立抽象产品角色Air 并创建函数play();具体产品角色为:Mideaair和Haierair。用户可直接在FactoryMethodconfig.xml文件中修改输出结果。
2.2.2类图设计
2.2.3运行及部分代码
抽象工厂角色Airfactory:
package Cold;
public interface Airfactory {
public Air produceAir();
}
抽象产品角色:
package Cold;
public interface Air {
public void play();
}
具体工厂角色、产品角色和客户端类
package Cold;
public class Haierfactory implements Airfactory {
public Air produceAir() {
System.out.println("海尔工厂生产海尔空调");
return new Haierair(); }
}
package Cold;
public class Haierair implements Air {
public void play() {
System.out.println("生产海尔空调...");
}
}
package Cold;
public class Test {
public static void main(String args[]){
try{
Air air;
Airfactory factory;
factory=(Airfactory)XMLUtil.getBean();
air=factory.produceAir();
air.play();}
catch(Exception e){
System.out.println(e.getMessage()); }
}
}
2.3抽象工厂模式
抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。根据里氏替换原则,任何接受父类型的地方,都应当能够接受子类型。
优点:分离了具体的类;使得易于交换产品系列;有利于产品的一致性
缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的工厂里加代码,又要在具体的里面加代码。
2.3.1题目及分析
电脑配件生产工厂生产内存、CPU等硬件设备,这些内存、CPU的品牌、型号并不一定相同,根据下面的“产品等级结构-产品族”示意图,使用抽象工厂模式实现电脑配件生产过程并绘制相应的类图,绘制类图并编程实现。
同一个工厂生产的不同产品为一个产品族。因此将CPU和RAM设为接口作为抽象产品角色,分别创建play()和use()函数;接口EFactory为抽象工厂角色;MacFactory和PcFactory作为具体工厂角色同时分别返回到具体产品角色MacCPU、MacRAM和PcCPU、PcRAM;配置文件读取类XMLtil,在配置文件中修改具体输出内容。
2.3.2类图设计
2.3.3运行及部分代码
抽象工厂角色:EFactory
package Computer;
public interface EFactory{
public RAM produceRAM();
public CPU produceCPU();}
抽象产品角色:CPU、RAM
package Computer;
public interface CPU {
public void play();
}
package Computer;
public interface RAM {
public void use();
}
具体工厂、具体产品角色:MacFactory、MacRAM、MacCPU
package Computer;
public class MacFactory implements EFactory{
public CPU produceCPU(){
return new MacCPU();
}
public RAM produceRAM(){
return new MacRAM();}
}
package Computer;
public class MacRAM implements RAM {
public void use() {
System.out.println("Mac的RAM使用中......");}
}
package Computer;
public class MacCPU implements CPU {
public void play() {
System.out.println("Mac的CPU运行中......");}
}
三.经验总结
了解和运用了简单工厂模式、工厂方法和抽象工厂方法,在画类图和修改代码中明白了这三种模式的不同之处。设计模式要灵活运用,根据不同需求在众多模式中选择最合适的模式,从而使程序有更大的可扩展性和尽量少的修改量。主要出现的问题是在编译过程中eclipse自带的jdk版本与操作系统中的java版本不一致,最终在项目属性中将jdk设置为1.7版本可成功运行。