了解设计模式 之 创建模式(一) -- 工厂模式

最近突发奇想,觉得学会了再多的框架、技术标准,很多因为没有什么机会使用,过段时间就全都忘掉了,还是真正感悟一些方法性的东西比较合适,有很多东西需要用的时候再学是完全来得及的。

说实话,设计模式的书也看过两遍了,不过总感觉还是记不住,最近发现一个好方法,把学习的心得贴出来,在写文章的时候可以更深入的了解要学习的知识,这也算我的一个学习方法吧。

闲话少说,进入正题。

设计模式总的来说可以分成三类:创建模式,结构模式,行为模式。

这篇文章主要讲的是创建模式的相关内容,创建模式主要包括工厂模式(Factory Pattern),建造者模式(Builder Pattern),原型模式(Prototype Pattern)和单例模式(Singleton Pattern),下面会一一的去解说。

1. 工厂模式(Factory Pattern)

说到工厂模式,每个人都会或多或少的有所了解。可能有些人会很快的在心里出现下面的这段代码:

public class SimpleFactory {

public Interface getInstance(String type) {
if (type.equals("type1")) {
return Product1;
} else if (type.equals("type2")) {
return Product1;
} else {
return DefaultProduct;
}
}
}


其实不然,这个#getInstance()方法是一种编程的小技巧,它把会变化的地方封装了起来(Encapsulate what varies),满足了设计的法则,但同时,当需求变更的时候,比如增加了更多种类的包子的时候,就要打开代码,重写getInstance()方法了,这是它的一个弊病。

而正宗的工厂模式又是什么样的呢?

下面来看一下工厂模式的其中一种,工厂方法模式(Factory Method Pattern)。

还是上边的例子,用工厂方法模式重写之后的代码如下所示:

public abstract class Factory {

public abstract Interface getInstance() {
}

public void someOperation() {
Interface i = getInstance();
i.someOperation();
}
}


这样,对于不同的Interface实现,就可以使用不同的工厂了。

public class ConcreteFactory extends Factory{
public Interface getInstance() {
return new Product1();
}
}


客户端程序可以这样编写

public class Client {
public static void main(String[] args){
test();
}

public static void test() {
Factory fac = new ConcreteFactory();
fac.someOperation();
}
}


这个就是工厂方法模式定义了一个生成对象的接口(Factory),但是让子类(ConcreteFactory)去决定到底要产生什么对象。

它的类图如下所示:

[img]http://zddava.iteye.com/upload/attachment/73309/59389f83-7bd4-3959-88aa-8db1e11d95f1.jpg[/img]

而另外一种工厂模式就是抽象工厂模式了(Abstract Factory Pattern),举一个现实一点的例子。

有一个很NB的方便面厂,它的方便面已经生产到了全国各主要城市,包括:北京,上海,杭州等等。

可是每个地方的人口味都不太一样(至少我了解到的是康师傅的方便面在杭州有东坡肉口味的,北方就没有),包括面饼和调料都是不一样的,所以导致了生产方便面时工艺的不同。

现在这个方便面公司请你来做一个订购方便面的系统,这个时候就可以让抽象工厂模式派上用场了。

可以先定义一个方便面类(其实是面饼)

public abstract class InstantNoodle{// 这个就是面饼类了
}


public abstract class Condiment{// 这个是调味品类
}


这两个加到一起就是一袋方便面了。

然后来定义一个抽象工厂

public abstract class Factory{
public InstantNoodle createInstantNoodle();

public Condiment createCondiment();
}


这样,所有的接口都定义完了,下面来看一下实现类。

比如说我要实现北京口味的方便面,那么我要做的是定义一个关于北京的工厂类。

public class BeijingFactory extends Factory{
public InstantNoodle createInstantNoodle(){
return new BeijingInstantNoodle();
}

public Condiment createCondiment(){
return new BeijingCondiment();
}
}


这里BeijingInstantNoodle和BeijingCondiment分别是继承了InstantNoodle和Condiment的特定面饼和调味品类。

另外如果还要生产杭州口味的方便面和调味品的话可以这样实现:

public class HangzhouFactory extends Factory{
public InstantNoodle createInstantNoodle(){
return new HangzhouInstantNoodle();
}

public Condiment createCondiment(){
return new HangzhouCondiment();
}
}


同样,HangzhouInstantNoodle和HangzhouCondiment分别是继承了InstantNoodle和Condiment的特定面饼和调味品类。

最后来写一个生产方便面的类,他需要一个具体的工厂作为传入的参数。

public class InstantNoodleStore(){
Factory factory = null;
public InstantNoodleStore(Factory factory){
this.factory = factory;
}

public BaggedInstantNoodle create(){// 生产方便面(BaggedInstantNoodle,这个是最终的袋装的产品)
InstantNoodle = factory.createInstantNoodle();
Condiment = factory.createCondiment();
return new BaggedInstantNoodle(InstantNoodle, Condiment);// 根据面饼和调味料制作袋装方便面
}
}


最后再写一个客户端程序

public class Client{
public static void main(String[] args){
test();
}
public static void test() {
// 制作北京口味的
Factory factory = new BeijingFactory();
InstantNoodleStore store = new InstantNoodleStore(factory);
store.create();

// 制作杭州口味的
factory = new HangzhouFactory();
store = new InstantNoodleStore(factory);
store.create();
}
}


这个就是抽象工厂模式了,它提供了一个创建相关联对象的接口,而不用知道这些相关联对象的具体实现类是什么。

它的类图如下所示:

[img]http://zddava.iteye.com/upload/attachment/74140/a85ff18d-ca49-35ee-9e56-f8772fd5cdef.jpg[/img]

有些人可能会说,用两个工厂方法模式不就可以实现抽象工厂了吗?我的答案是抽象工厂模式生成的产品间会有一定的关系,比如上边例子中写的都是同一个地域口味的产品。可以说,工厂方法模式重视的是对象的创建,代码是围绕创建这个主题的,而抽象工厂模式强调的是产品线的概念,每次都会生成一些列具有逻辑上相关的对象,代码是围绕在统一产品线,令同一个工厂可以生成一些列整齐划一的产品这个主题的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值