准备找工作那会看到了一本神书,《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();
}
}
至此工厂模式就算是总结完了,还留了一个小题,就是在抽象工厂中,让一个工厂生产多个产品。
这里有一个坑,也同时给我自己挖了一个,下面晒一下我的答案:
首先我新建了一个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();
看一下测试
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();
}
}
}
建造者模式是可以创造出很多复杂的东西,所以以后在用的时候可以考虑清楚,那种模式更适合