最近突发奇想,觉得学会了再多的框架、技术标准,很多因为没有什么机会使用,过段时间就全都忘掉了,还是真正感悟一些方法性的东西比较合适,有很多东西需要用的时候再学是完全来得及的。
说实话,设计模式的书也看过两遍了,不过总感觉还是记不住,最近发现一个好方法,把学习的心得贴出来,在写文章的时候可以更深入的了解要学习的知识,这也算我的一个学习方法吧。
闲话少说,进入正题。
设计模式总的来说可以分成三类:创建模式,结构模式,行为模式。
这篇文章主要讲的是创建模式的相关内容,创建模式主要包括工厂模式(Factory Pattern),建造者模式(Builder Pattern),原型模式(Prototype Pattern)和单例模式(Singleton Pattern),下面会一一的去解说。
1. 工厂模式(Factory Pattern)
说到工厂模式,每个人都会或多或少的有所了解。可能有些人会很快的在心里出现下面的这段代码:
其实不然,这个#getInstance()方法是一种编程的小技巧,它把会变化的地方封装了起来(Encapsulate what varies),满足了设计的法则,但同时,当需求变更的时候,比如增加了更多种类的包子的时候,就要打开代码,重写getInstance()方法了,这是它的一个弊病。
而正宗的工厂模式又是什么样的呢?
下面来看一下工厂模式的其中一种,工厂方法模式(Factory Method Pattern)。
还是上边的例子,用工厂方法模式重写之后的代码如下所示:
这样,对于不同的Interface实现,就可以使用不同的工厂了。
客户端程序可以这样编写
这个就是工厂方法模式定义了一个生成对象的接口(Factory),但是让子类(ConcreteFactory)去决定到底要产生什么对象。
它的类图如下所示:
[img]http://zddava.iteye.com/upload/attachment/73309/59389f83-7bd4-3959-88aa-8db1e11d95f1.jpg[/img]
而另外一种工厂模式就是抽象工厂模式了(Abstract Factory Pattern),举一个现实一点的例子。
有一个很NB的方便面厂,它的方便面已经生产到了全国各主要城市,包括:北京,上海,杭州等等。
可是每个地方的人口味都不太一样(至少我了解到的是康师傅的方便面在杭州有东坡肉口味的,北方就没有),包括面饼和调料都是不一样的,所以导致了生产方便面时工艺的不同。
现在这个方便面公司请你来做一个订购方便面的系统,这个时候就可以让抽象工厂模式派上用场了。
可以先定义一个方便面类(其实是面饼)
这两个加到一起就是一袋方便面了。
然后来定义一个抽象工厂
这样,所有的接口都定义完了,下面来看一下实现类。
比如说我要实现北京口味的方便面,那么我要做的是定义一个关于北京的工厂类。
这里BeijingInstantNoodle和BeijingCondiment分别是继承了InstantNoodle和Condiment的特定面饼和调味品类。
另外如果还要生产杭州口味的方便面和调味品的话可以这样实现:
同样,HangzhouInstantNoodle和HangzhouCondiment分别是继承了InstantNoodle和Condiment的特定面饼和调味品类。
最后来写一个生产方便面的类,他需要一个具体的工厂作为传入的参数。
最后再写一个客户端程序
这个就是抽象工厂模式了,它提供了一个创建相关联对象的接口,而不用知道这些相关联对象的具体实现类是什么。
它的类图如下所示:
[img]http://zddava.iteye.com/upload/attachment/74140/a85ff18d-ca49-35ee-9e56-f8772fd5cdef.jpg[/img]
有些人可能会说,用两个工厂方法模式不就可以实现抽象工厂了吗?我的答案是抽象工厂模式生成的产品间会有一定的关系,比如上边例子中写的都是同一个地域口味的产品。可以说,工厂方法模式重视的是对象的创建,代码是围绕创建这个主题的,而抽象工厂模式强调的是产品线的概念,每次都会生成一些列具有逻辑上相关的对象,代码是围绕在统一产品线,令同一个工厂可以生成一些列整齐划一的产品这个主题的。
说实话,设计模式的书也看过两遍了,不过总感觉还是记不住,最近发现一个好方法,把学习的心得贴出来,在写文章的时候可以更深入的了解要学习的知识,这也算我的一个学习方法吧。
闲话少说,进入正题。
设计模式总的来说可以分成三类:创建模式,结构模式,行为模式。
这篇文章主要讲的是创建模式的相关内容,创建模式主要包括工厂模式(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]
有些人可能会说,用两个工厂方法模式不就可以实现抽象工厂了吗?我的答案是抽象工厂模式生成的产品间会有一定的关系,比如上边例子中写的都是同一个地域口味的产品。可以说,工厂方法模式重视的是对象的创建,代码是围绕创建这个主题的,而抽象工厂模式强调的是产品线的概念,每次都会生成一些列具有逻辑上相关的对象,代码是围绕在统一产品线,令同一个工厂可以生成一些列整齐划一的产品这个主题的。