设计模式之工厂模式、建造者模式

准备找工作那会看到了一本神书,《Head First 设计模式》,从此对设计模式有了很深的亲睐,但是因为自己的项目经验少的可怜,所以也基本没有用过这些神一样的方法,时间一长也就都忘干净了。现在工作了,师兄给了一个500M的代码,让我吃透它。这期间真的有很多问题,很迷惑。忽然想起了我之前看的书,于是重新拿出来温习。

如果说设计模式是圣经,那么这本书就是小人漫画版的启蒙圣经。入门看真的很好,但因为工作需要没有这么多时间,快餐式的是最合适的。于是在网上看到了一个网址,介绍23种设计模式很是靠谱。http://zz563143188.iteye.com/blog/1847029 这是这位大牛的网址。

以前看书的时候,感觉工厂模式种类繁多,根本就分不清楚,但是看了他的博客之后,有种拨云见月的感觉。于是乎就自己写下了这几个工厂模式的例子来练习,实现实例没有自己设计是参照网上的。

写完之后就感觉自己分清并掌握了这几个模式,下面就总结一下。

工厂模式是三类设计模式中的创建式模式,工厂模式分为三种,简单工厂方法,复杂工厂,还有抽象工厂

下面先看一下他们的实现


一,简单工厂模式

首先定义一个Isend接口

public interface Isend {
	public void sendMessage();
}
然后new几个sender,实现Isend接口
public class MailSender implements Isend {

	public void sendMessage() {
		// TODO Auto-generated method stub
		System.out.println("Use MailSender send the message!");
	}

}

public class PhoneSender implements Isend{

	public void sendMessage() {
		// TODO Auto-generated method stub
		System.out.println("Use PhoneSender send the message!");
	}

}
然后就是做一个工厂,让工厂来生产这几个sender

public class SenderFactory {
	public Isend productSender(String type) {
		if("Mail".equals(type)) {
			return new MailSender();
		}else if("Phone".equals(type)) {
			return new PhoneSender();
		}else 
			return new NullSender();
	}
}
其中红色部分,就是暴露出了简单工厂的缺点,就是当type的类型和系统定义的步一样时,有可能是输入错误等,返回的就是一个空类型了,这是简单工厂的天生缺点

看一下测试

public class Test {
	public static void main(String[] args) {
		SenderFactory factory = new SenderFactory();
		Isend mailSender = factory.productSender("Mail");
		mailSender.sendMessage();
		
		Isend phoneSender = factory.productSender("Phone");
		phoneSender.sendMessage();
		
		Isend errorySender = factory.productSender("123");
		errorySender.sendMessage();
		
	}
}
测试结果:

Use MailSender send the message!
Use PhoneSender send the message!
No SenderFactory product sender!

因为这个工厂相当于单个生产线,所以每种产品都会从这条生产线中产出,所以如果输入是本来生产线中没有的,那么就只能报错了。根据这种情况,于是就想可以再多出几条生产线啊。就是下面的复杂工厂该出场了。

二、复杂工厂:

其他的都一样,就是在工厂中多加几条生产线,所以直接看SenderFactory类就可以了

package com.designpattern.complexfactory.factory;

import com.designpattern.complexfactory.isend.Isend;
import com.designpattern.complexfactory.sender.MailSender;
import com.designpattern.complexfactory.sender.PhoneSender;

public class SenderFactory {
	public Isend productMailSender() {
		return new MailSender();
	} 
	
	public Isend productPhoneSender() {
		return new PhoneSender();
	}
}
在这里,我做了两条生产线,每条生产线只负责生产一种产品,所以,这样就没有输入错误的情况了,看看测试

public class Test {
	public static void main(String[] args) {
		SenderFactory factory = new SenderFactory();
		Isend mailSender = factory.productMailSender();
		mailSender.sendMessage();
		
		Isend phoneSender = factory.productPhoneSender();
		phoneSender.sendMessage();
		
	}
}
解决了?好像发现了两个问题。

1,工厂方法里不需要创建实例,直接调用就行,那好办就把它设置为静态工厂,就实现了不需要实例化,直接创建。

public class SenderFactory {
	public static Isend productMailSender() {
		return new MailSender();
	} 
	
	public static Isend productPhoneSender() {
		return new PhoneSender();
	}
}
下面看一下测试

public static void main(String[] args) {
		Isend mailSender = SenderFactory.productMailSender();
		mailSender.sendMessage();
		
		Isend phoneSender = SenderFactory.productPhoneSender();
		phoneSender.sendMessage();
		
	}

2,设计模式崇尚的是对扩展开放,对修改关闭。当有新的需求有新的产品设计出来需要生产的时候,那么就只能更改SenderFactory这个类了,那么不就是违背这个设计原则了吗。可以设想,把工厂也做成多个,当有新的产品时,就建一座工厂,这样原来的工厂就不需要更改了,就实现了工厂之间的松耦合。

于是抽象工厂就这么产生了

抽象工厂:

抽象工厂就是把处理工厂的方法和处理生产线的方法一样

首先看一下IFactory接口

public interface IFactory {
	public Isend productSender();
}
所有的工厂都实现此接口,也就意味着所有的工厂都可以生产产品,看一下这几个工厂

public class MailSender implements Isend{

	public void SendMessage() {
		// TODO Auto-generated method stub
		System.out.println("Use MailSender send the message!");
	}

}

public class PhoneSender implements Isend {

	public void SendMessage() {
		// TODO Auto-generated method stub
		System.out.println("Use PhoneSender send the message!");
	}

}
这里我又新建了一个qq工厂,来发送qq消息

public class QQSender implements Isend {

	public void SendMessage() {
		// TODO Auto-generated method stub
		System.out.println("User QQSender send the message!");
	}

}
工厂看完了,看一下消息发送器

public class MailSender implements Isend{

	public void SendMessage() {
		// TODO Auto-generated method stub
		System.out.println("Use MailSender send the message!");
	}

}

public class PhoneSender implements Isend {

	public void SendMessage() {
		// TODO Auto-generated method stub
		System.out.println("Use PhoneSender send the message!");
	}

}

public class QQSender implements Isend {

	public void SendMessage() {
		// TODO Auto-generated method stub
		System.out.println("User QQSender send the message!");
	}

}

每一种发送器都是由不同的工厂生产出来的,当然也可以一个工厂生产多种产品,你可以试着改一下,当练手。

下面看一下测试

public class Test {
	public static void main(String[] args) {
		IFactory mailFactory = new MailSenderFactory();
		Isend mailSend = mailFactory.productSender();
		mailSend.SendMessage();
		
		IFactory phoneFactory = new PhoneSenderFactory();
		Isend phoneSend = phoneFactory.productSender();
		phoneSend.SendMessage();
		
		IFactory qqFactory = new QQSenderFactory();
		Isend qqSend = qqFactory.productSender();
		qqSend.SendMessage();
	}
}

在这个例子中,新加的qq发送器是由qq工厂new出来的,不影响Mail 和 Phone工厂,实现了对扩展开放,对修改关闭的原则。

至此工厂模式就算是总结完了,还留了一个小题,就是在抽象工厂中,让一个工厂生产多个产品。


这里有一个坑,也同时给我自己挖了一个,下面晒一下我的答案:

首先我新建了一个WeiSender,想让QQSenderFactory也同时能生产WeiSender

public class WeiSender implements Isend {

	public void SendMessage() {
		// TODO Auto-generated method stub
		System.out.println("Use WeiSender send the message!");
	}

}
把QQSenderFactory类做了一下调整

public class QQSenderFactory implements IFactory{

	public Isend productSender() {
		// TODO Auto-generated method stub
		return new QQSender();
	}
	
	public Isend productWeiSender() {
		return new WeiSender();
	}

}
其中红色部分是我加的方法

于是在测试的时候,我就想直接用

IFactory qqFactory = new QQSenderFactory();
生产出来的qqFactory来执行productWeiSender()方法,但是发现是错误的,这里就是个坑,回头看qqFactory是怎么来的,是由IFactory来的,那么就只能执行IFactory接口中带有的方法啦。

所以如果还想执行其他的方法,那就得:

QQSenderFactory qqf = new QQSenderFactory();
		Isend qqs = qqf.productWeiSender();
		qqs.SendMessage();

使用这种方法来new一个qqFactory就可以执行QQSenderFactory中的所哟方法了。


看一下测试

Use MailSender send the message!
Use PhoneSender send the message!
User QQSender send the message!
Use WeiSender send the message!

建造者模式


看完了工厂模式,是不是觉得意犹未尽,还差点啥?

对了,工厂模式创建的是单个类的模式,工厂可是可以根据订货单来大批量生产的。

于是建造者模式就诞生了。

下面看一下他的代码,相信一看代码就很明确了

public interface ISend {
	public void Send() ;
}

public class MailSender implements ISend {

	public void Send() {
		// TODO Auto-generated method stub
		System.out.println("Use MailSender send the message!");
	}

}

public interface IFactory {
	
	public List productSender(int count) ;
}

public class MailSenderFactory implements IFactory {

	private List list ; 
	
	public MailSenderFactory() {
		list = new ArrayList();
	}
	
	public List productSender(int count) {
		for(int i = 0; i < count; i++) {
			list.add(new MailSender());
		}
		return list;
	}
	
	
}

public class Test {
	public static void main(String[] args) {
		MailSenderFactory mailFactory = new MailSenderFactory();
		List list = mailFactory.productSender(3);
		for(int i = 0; i < list.size(); i++) {
			ISend sender = (ISend) list.get(i);
			sender.Send();
		}
	}
}

不用多说了吧,我想应该一看就能明白

建造者模式是可以创造出很多复杂的东西,所以以后在用的时候可以考虑清楚,那种模式更适合

你可能感兴趣的:(设计模式)