您的位置:首页 > 其它

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

2015-01-14 22:01 399 查看
准备找工作那会看到了一本神书,《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
<span style="color:#ff0000;">return new NullSender();</span>
}
}
其中红色部分,就是暴露出了简单工厂的缺点,就是当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 <span style="color:#ff0000;">static</span> Isend productMailSender() {
return new MailSender();
}

public <span style="color:#ff0000;">static</span> 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();
}

<span style="color:#ff0000;">public Isend productWeiSender() {
return new WeiSender();
}</span>

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

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

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

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

<span style="color:#ff0000;">QQSenderFactory qqf = new QQSenderFactory();</span>
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<ISend> productSender(int count) ;
}


public class MailSenderFactory implements IFactory {

private List<ISend> list ;

public MailSenderFactory() {
list = new ArrayList();
}

public List<ISend> 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();
}
}
}


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

建造者模式是可以创造出很多复杂的东西,所以以后在用的时候可以考虑清楚,那种模式更适合
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐