Java学习笔记(疯狂Java讲义第三版)——简单工厂设计模式

案例:
假设需要设计一个电脑类,类名用Computer表示。然后需要在该电脑类上装一台打印机,那么接下来定义一个打印机的了,名为Printer。
我们通过简单的语法定义来掩饰:
//打印机类
class Printer
{
//其他内容省略
}

//计算机类
class Computer
{
Printer p;//安装Printer类型的打印机
public Computer(Printer p){
this.p = p;
}
//其他内容省略
}
通过上述代码,在Computer类中直接定义了Printer类型的成员变量。可以看成在电脑上安装了一台打印机。
那么现在,假设电脑上不需要Printer类型的"打印机"了,想要引入更好型号的打印机BetterPrinter打印机。
class BetterPrinter
{
//其他内容省略。
}

此时如果先要将Printer类型的打印机换成BetterPrinter类型的打印机需要修改Computer类,即
class Computer
{
BetterPrinter bp;//更换BetterPrinter类型的打印机
public BetterPrinter(BetterPrinter bp){
this.bp = b;
}
}
注意,上述操作是需要重写源代码的。如果编写的整个应用程序好多地方都用到了Computer类型的对象中的成员变量p,那么就需要全部修改。
总结写,上述写法,导致如果需要修改Computer类中的成员首先就需要修改Computer类的源代码,其次,程序中用到成员p的地方也要全部进行修改。

我们知道在现实生活中,若果需要给电脑换打印机的话,只需要拔掉原来的打印机,插上新的即可。那么接下来,我们就要在代码中实现这一功能。

//定义一个Output接口
interface Outerput
{
//内容省略
}

class Printer implements Output//Printer类实现该接口
{
//内容省略
}

class BetterPrinter implements Output//BetterPrinter类实现该接口
{
//内容省略
}

class Computer
{
Output out;
public Computer(Output out)
{
this.out = out;
}
}

public class Test
{
public static void main(String args)
{
Printer p = new Printer();//创建一个对象
BetterPrinter bp = new BeterPrinter();//创建一个对象
Computer c = new Computer§;//先安装p型号打印机
c.out = bp;//在换成BetterPrinter类型的打印机
}
}
通过上述代码,解决了Computer类更换打印机时,需要重写Computer类中源代码的情况。但是,如果此时又有了一台新的打印SuperPrinter,还要更换设备。当然该打印机也是实现了Output接口的,此时仍需修改main函数中的源代码。
public class Test
{
public static void main(String args)
{
SuperPrinter sp = new SuperPrinter();
c.out = sp;
}
}
注意虽然看上去很简单,但是还是在main函数中对其进行的修改,所以还是不够好。
我们设想下,若果有一块专门的代码专门用来提供“打印机”,当需要更换打印机型号的时候只需要在该代码段中进行即可。

上述还是不够好,上述只是实现了打印机可以随意的更换,而不需要对电脑类本身进行代码修改。但是并没有实现打印机和电脑的完全分离。
我们可以定义一个类,专门用来给Computer提供打印机。看代码
class OutputFactory//定义一个专门用来给Computer类提供打印机
{
public Output getOutput(){
return new Printer();//返回Pinter型号的打印机
}
}
class Test
{
public static void main(String[] args){
OutputFactory opf = new OutputFactory();//创建一个工厂对象
Computer c = new Computer(opf.getOutput());//将Printer型号的打印机给Computer
}
}
如果此时需要将Printer型号的打印机换成BetterPrinter只需修改getOutput方法中的return语句即可,即改成retrun BetterPrinter。

在这里充分的体现了接口的作用,由于Computer类中的成员变量为Ouput接口类型,那么所有实现了该接口的类的对象都可以(Printer、BetterPrinter)都可以直接赋值给Computer类中定义的Ouput类型的成员变量。

本例最开始的没有利用接口就好比我们主板上的集成显卡,如果想要更换就只能更换主板(重写类中的代码)。利用了接口之后就相当于主板上的独立显卡了,更换的时候,只要更换成符合该插槽型号的显卡即可。
最后的改版提供了一个专门提供打印机的类。个人感觉,就相当于有了一个负责修理电脑的助理,你只要把你的需求告诉他,他就会帮你进行替换。

上述的例子,通过OuputFactory类将Computer类和相关的Printer类完全的隔开,起到了一个桥梁的作用。对于OuputFactory来说,唯一的作用就是为Computer提供所需的打印机型号,可以简单的理解成专门用来生产打印机的工厂,所以这种设计模式也称为工厂设计模式。

我们来对上述代码记性补全实现(代码取自疯狂Java讲义第三版)
//定义Output接口
interface Output
{
int MAX_CACHE_LINE = 50;//规定打印机的缓存长度
void out();//定义实现改接口的类都要有输出的功能
void getData(String msg);//定义实现该接口的类都有存入数据功能
/*
打印机打印内容都是先存入数据,然后再打印
*/
}

//定义product接口
interface Product//固定实现该接口的类都要有生产日期
{
int getProduceTim();
}

//定义Printer打印机
class Printer implements Output, Product
{

//打印机的总容量
private String[] printData = new String[MAX_CACHE_LINE];
private int dataNum = 0;//定义需要打印的作业数
public void out()//重写Output中的out()方法
{
	while (dataNum > 0){
		System.out.println("打印机打印:" + printData[]);	
		System.arraycopy(printData, 1, printData, 0, --dataNum);
		//printData,1:将数组的内容整体前移一位
		//printData,0:移动的起始位置,即从数组的第一个元素开始往后的没一个
		//元素都移动一位
		//最后一个表示移动后数组的长度,原长度是dataNum,
		//整体前移一位之后总长度变为dataNum-1
		//注意,最前面的移出去了,也就是没有了,所以长度要减一
	}
}

public void getData(String msg)//实现Output中的getData()方法
{
	if(dataNum > MAX_CACHE_LINE){
		System.out.println("内容已满,不能打印");	
	}esle{
		printData[dataNum++] = msg;	
	}
}

public int getProduceTime(){
	return 45;//用来表示打印机的生产日期
}//重写Product中的getProduceTime()方法

}

//定义BetterPrinter打印机
class BetterPrinter implements Output, Product
{
private String[] printData = new String[2*MAX_CHACHE_LINE];

public void out(){
	while(dataNum > 0){
		System.out.println("BetterPrinter打印机正在打印:" printData[dataNum]);
		System.arraycopy(printData, 1, printData, 0, --dataNu
		m);
	}
}

public viod getData(String msg){
	if (dataNum >= 2*MAX_CACHE_LINE){
		System.out.println("内容已满");//可以比Printer存入更多的内容
	}else{
			printData[dataNum++] = msg;
	}
}
public int getProduceTime(){
	return 55;//返回生产日期
}

}

//定义打印机生产工厂
class OutputFactory
{
public Output getOutput(){
return new Printer();
}
}

//定义电脑类
class Computer
{
Output out;
public Computer(Output out){
this.output = output;
}

//定义一个获取打印内容的方法
//优点是可以通过电脑来控制打印机进行打印
public void keyIn(String msg){
	out.getData(msg);
}

//定义一个打印输出的方法
//有点是可以通过电脑来调用打印机进行打印
public void print(){
	out.out();
}

}

public class Test
{
public static void main(String[] args){
OutputFactory of = new OutputFactory();
Computer c = new Computer(of.getOutput());
c.keyIn(“Hello World”);//通过电脑给打印机输入内容
c.print();//通过电脑用打印机进行打印
}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值