简单工厂模式、工厂方法模式、抽象工厂模式的练习

一、题目分析
1、简单工厂模式
使用简单工厂模式模拟女娲(Nvwa)造人(Person),如果传入参数M,则返回一个Man对象,如果传入参数W,则返回一个Woman对象,请实现该场景。现需要增加一个新的Robot类,如果传入参数R,则返回一个Robot对象,对代码进行修改并注意女娲的变化。

2、工厂方法模式
海尔工厂(Haier)生产海尔空调(HaierAirCondition),美的工厂(Midea)生产美的空调(MideaAirCondition) 。使用工厂方法模式描述该场景,绘制类图并编程实现。

3、抽象工厂模式
电脑配件生产工厂生产内存、CPU等硬件设备,这些内存、CPU的品牌、型号并不一定相同,根据下面的“产品等级结构-产品族”示意图,使用抽象工厂模式实现电脑配件生产过程并绘制相应的类图,绘制类图并编程实现。

这里先对三种工厂模式进行介绍
简单工厂模式
简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。
工厂方法模式
工厂方法模式是一种实现了“工厂”概念的面向对象设计模式。就像其他创建型模式一样,它也是处理在不指定对象具体类型的情况下创建对象的问题。工厂方法模式的实质是“定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。”
抽线工厂模式
抽象工厂模式提供了一种方式,可以将一组具有同一主题的单独的工厂封装起来。在正常使用中,客户端程序需要创建抽象工厂的具体实现,然后使用抽象工厂作为接口来创建这一主题的具体对象。客户端程序不需要知道(或关心)它从这些内部的工厂方法中获得对象的具体类型,因为客户端程序仅使用这些对象的通用接口。抽象工厂模式将一组对象的实现细节与他们的一般使用分离开来。

分析:简单工厂模式主要是对一个产品不同种类的设计,这些具体的不同种类的产品都来源于一个基类,只是在不同的子类继承基类之后对父类方法进行重写,实现子类的具体产品种类。在使用的时候只需要将表示具体产品的参数传入方法即可获得一个相应的产品示例。

工厂方法模式将产品交给专门的子类来完成,不再由一个类完成多个产品,这种抽象化的结果使这种结构可以在不修改具体工厂类的情况下引进新的产品,如果出现新的产品类型,只需要为这种新类型的产品创建一个具体的工厂类就可以获得该新产品的实例,这一特点无疑使得工厂方法模式更加符合“开闭原则”。

抽象工厂模式不再一个类只完成一类产品的创建,而是进行一系列产品的创建,形成一个产品族。抽象工厂模式与工厂方法模式最大的区别在于,工厂方法模式针对的是一个产品等级结构,而抽象工厂模式则需要面对多个产品等级结构,一个工厂等级结构可以负责多个不同产品等级结构中的产品对象的创建 。当一个工厂等级结构可以创建出分属于不同产品等级结构的一个产品族中的所有对象时,抽象工厂模式比工厂方法模式更为简单、有效率。

二、类图设计
1、简单工厂模式类图
简单工厂模式、工厂方法模式、抽象工厂模式的练习_第1张图片
2、工厂方法模式类图
简单工厂模式、工厂方法模式、抽象工厂模式的练习_第2张图片
3、抽象工厂模式类图
简单工厂模式、工厂方法模式、抽象工厂模式的练习_第3张图片
三、程序实现
1、简单工厂模式
抽象人的种类作为一个接口

//写一个接口表示抽象的人
public interface Person {
	public void play();
}
//女娲造人的实现过程,相当于工厂模式中的工厂
public class Nvwa {
	public static Person createPerson(String person) {
		if(person.equalsIgnoreCase("Man"))
			return new Man();
		else if(person.equalsIgnoreCase("Woman")) 
			return new Woman();
		else if(person.equalsIgnoreCase("Robot"))
			return new Robot();
		else return null;
		}
}
//人的种类实现类,具体实现男人的类
public class Man implements Person{
	public Man() {
		System.out.println("女娲正在造人。");
	}
	public void play() {
		System.out.println("这是一个男人。");
	}
}

//人的种类实现类,具体实现女人的种类
public class Woman implements Person{
	public Woman() {
		System.out.println("女娲正在造人。");
	}
	public void play()
	{
		System.out.println("这是一个女人.");
	}
}
//人的种类实现类,具体实现机器人的种类
public class Robot implements Person {
	public Robot() {
		System.out.println("女娲正在造人。");
	}
	public void play()
	{
		System.out.println("这是一个机器人.");
	}
}
public class main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		try {
			Nvwa n=new Nvwa();
			n.createPerson("woman").play();//调用人类的创建方法并显示人的种类
		}catch(NullPointerException e) {
			System.out.println("没有这一类人。");
		}
	}
}

2、工厂方法模式

//抽象工厂接口
public interface Factory {
	public Product CreateProduct();//返回抽象产品的示例
}
//抽象产品接口
public interface Product {
	public void show();//抽象方法,展示出产品的情况。
}
//产品具体实现类,空调实现抽象产品的接口
public class Aircondition implements Product{
	public  void show() {
		System.out.println("正在生产空调");
	}
}

//抽象工厂实例化,Midea工厂实现抽象工厂接口
public class MideaFactory implements Factory{
	public Product CreateProduct() {
		System.out.println("美的工厂正在工作。");
		return new Aircondition();//返回抽象产品的示例,即空调
	}
}
//抽象工厂实例化,Haier工厂实现抽象工厂接口
public class HaierFactory implements Factory{
	public Product CreateProduct() {
		System.out.println("海尔工厂正在工作。");
		return new Aircondition();//返回抽象产品的示例,即空调
	}
}
//客户端类,对抽象工厂进行实例化,并调用生产方法生产对应品牌的产品
public class Client {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Factory m=new MideaFactory();//抽象工厂实例化,通过Midea工厂实例化抽象工厂
		m.CreateProduct().show();//Midea工厂调用抽象方法生产产品
		
		m=new HaierFactory();//通过Haier工厂实例化抽象工厂
		m.CreateProduct().show();//Haier工厂调用抽象方法生产产品
	}
}

3、抽象工厂模式

//抽象工厂接口
public interface AbstractFactory {
	public  RAM createRAM();//抽象方法,用于返回RAM接口的示例
	public  CPU createCPU();//抽象方法,用于返回CPU接口的实例
}

//CPU产品接口
public interface CPU {
	public void show_CPU();//抽象方法,展示产品的种类

}

//RAM产品接口
public interface RAM {
	public void show_RAM();//抽象方法,展示产品的种类
}

//具体工厂类,Mac工厂实现工厂接口
public class MacFactory implements AbstractFactory{
	public  RAM createRAM() {
		System.out.println("这是MAC工厂的产品。");
		return new MacRAM();//返回Mac工厂的RAM示例
	}
	public  CPU createCPU() {
		System.out.println("这是MAC工厂的产品。");
		return new MacCPU();//返回Mac工厂的CPU示例
	}
}

//具体工厂类,Pc工厂实现工厂接口
public class PcFactory implements AbstractFactory{
	public  RAM createRAM() {
		System.out.println("这是Pc工厂的产品。");
		return new PcRAM();//返回Pc工厂的RAM示例
	}
	public  CPU createCPU() {
		System.out.println("这是Pc工厂的产品。");
		return new PcCPU();//返回Pc工厂的CPU示例
	}
}

//CPU具体实现类,Mac工厂CPU类实现CPU接口
public class MacCPU implements CPU{
	public void show_CPU() {
		System.out.println("CPU");
	}
}

//CPU具体实现类,Pc工厂CPU类实现CPU接口
public class PcCPU implements CPU{
	public void show_CPU() {
		System.out.println("CPU");
	}

}

//RAM具体实现类,Pc工厂RAM类实现RAM接口
public class PcRAM implements RAM{
	public void show_RAM() {
		System.out.println("RAM");
	}

}

//RAM具体实现类,Mac工厂RAM类实现RAM接口
public class MacRAM implements RAM{
	public void show_RAM() {
		System.out.println("RAM");
	}

}

//客户端类通过实例化具体的工厂类,并调用其创建不同目标产品的方法创建不同具体产品类的实例
public class Client {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		AbstractFactory factory=new PcFactory();//创建Pc工厂示例
		factory.createCPU().show_CPU();//工厂调用生产产品的方法,并展示产品的种类
		factory.createRAM().show_RAM();
		
		factory=new MacFactory();//创建Mac工厂示例
		factory.createCPU().show_CPU();
		factory.createRAM().show_RAM();
	}
}

四、运行结果
1、简单工厂模式结果
简单工厂模式、工厂方法模式、抽象工厂模式的练习_第4张图片
2、工厂方法模式
简单工厂模式、工厂方法模式、抽象工厂模式的练习_第5张图片
3、抽象工厂模式
简单工厂模式、工厂方法模式、抽象工厂模式的练习_第6张图片
五、总结
以下是我在网上收集的关于这三个模式各自的优缺点以及适用场景。
简单工厂模式的优点
*工厂类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的责任,而仅仅“消费”产品;简单工厂模式通过这种做法实现了对责任的分割,它提供了专门的工厂类用于创建对象。
*客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,对于一些复杂的类名,通过简单工厂模式可以减少使用者的记忆量。
*通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。
简单工厂模式的缺点¶
*由于工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。
*使用简单工厂模式将会增加系统中类的个数,在一定程序上增加了系统的复杂度和理解难度。
*系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。
*简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构。
适用环境
在以下情况下可以使用简单工厂模式:
*工厂类负责创建的对象比较少:由于创建的对象较少,不会造成工厂方法中的业务逻辑太过复杂。
*客户端只知道传入工厂类的参数,对于如何创建对象不关心:客户端既不需要关心创建细节,甚至连类名都不需要记住,只需要知道类型所对应的参数。

工厂方法模式的优点
*在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节,用户只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名。
*基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它能够使工厂可以自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。工厂方法模式之所以又被称为多态工厂模式,是因为所有的具体工厂类都具有同一抽象父类。
*使用工厂方法模式的另一个优点是在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了。这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。
工厂方法模式的缺点
*在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。
*由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。
适用环境
在以下情况下可以使用工厂方法模式:
一个类不知道它所需要的对象的类:在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体的产品对象由具体工厂类创建;客户端需要知道创建具体产品的工厂类。
一个类通过其子类来指定创建哪个对象:在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏代换原则,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。
将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定,可将具体工厂类的类名存储在配置文件或数据库中。

抽象工厂模式的优点
*抽象工厂模式隔离了具体类的生成,使得客户并不需要知道什么被创建。由于这种隔离,更换一个具体工厂就变得相对容易。所有的具体工厂都实现了抽象工厂中定义的那些公共接口,因此只需改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。另外,应用抽象工厂模式可以实现高内聚低耦合的设计目的,因此抽象工厂模式得到了广泛的应用。
*当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。这对一些需要根据当前环境来决定其行为的软件系统来说,是一种非常实用的设计模式。
*增加新的具体工厂和产品族很方便,无须修改已有系统,符合“开闭原则”。
抽象工厂模式的缺点
*在添加新的产品对象时,难以扩展抽象工厂来生产新种类的产品,这是因为在抽象工厂角色中规定了所有可能被创建的产品集合,要支持新种类的产品就意味着要对该接口进行扩展,而这将涉及到对抽象工厂角色及其所有子类的修改,显然会带来较大的不便。
*开闭原则的倾斜性(增加新的工厂和产品族容易,增加新的产品等级结构麻烦)。
适用环境¶
在以下情况下可以使用抽象工厂模式:
*一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有类型的工厂模式都是重要的。
*系统中有多于一个的产品族,而每次只使用其中某一产品族。
*属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。
*系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。

以下是这些关于设计模式总结参考的博客,写的非常详细建议大家可以看看。
https://designpatterns.readthedocs.io/zh_CN/latest/creational_patterns/abstract_factory.html

https://designpatterns.readthedocs.io/zh_CN/latest/creational_patterns/simple_factory.html

https://designpatterns.readthedocs.io/zh_CN/latest/creational_patterns/factory_method.html

你可能感兴趣的:(作业,设计模式,java)