跟屌丝大哥学习设计模式

  • 时间:
  • 浏览:3

11

public class ConcreteProduct1 extends Product {

      抽象产品类代码如代码清单8-8所示。

15

41

9

11

23

}

11

19

36

3

public class HumanFactory {

12

13

      场景类的调用妙招如代码清单8-12所示。

16

      何为延迟初始化(Lazy initialization)?另另三个多对象被消费完毕后,我太大 说立刻释放,工厂类保持其初始情况,听候再次被使用。延迟初始化是工厂妙招模式的另另三个多扩展应用,其通用类图如图8-6所示。

15

4

27

      HumanFactory类仅有另另三个多地方变化:再加继承抽象类,并在createHuman前增加static关键字。工厂类地处变化,也一块儿引起了调用者NvWa的变化,如代码清单8-14示。

}

      运行结果还是相同。大伙儿儿回顾一下,每另另三个多产品类都对应了另另三个多创建类,好处也不 创建类的职责清晰,否则 特征简单,否则 给扩展性和维护性带来了一定的影响。为哪几个那么说呢?可能性要扩展另另三个多产品类,就须要建立另另三个多相应的工厂类,也不 就增加了扩展的难度。可能性工厂类和产品类的数量相同,维护时须要考虑另另三个多对象之间的关系。

2

      代码还比较简单,通过定义另另三个多Map容器,容纳所有产生的对象,可能性在Map容器中可能性有的对象,则直接取出返回,可能性那么,则根据须要的类型产生另另三个多对象并放上去到Map容器中,以方便下次调用。

System.out.println("\n--发明家 权的第三批人是黄色人种--");

4

public class ConcreteProduct2 extends Product {

}

32

try {

public class NvWa {

13

代码清单8-8 抽象产品类

blackHuman.getColor();

代码清单8-13 简单工厂模式中的工厂类

2

private static final Map<String,Product> prMap = new HashMap();

22

19

blackHuman.getColor();

4

31

      人种有了,八卦炉有了,负责生产的女娲都有了,激动人心的时刻到来了,大伙儿儿运行一下,结果如下所示。

public Human createHuman() {

7

Human whiteHuman = YinYangLu.createHuman(WhiteHuman.class);

24

public abstract class AbstractHumanFactory {

      工厂妙招模式的通用类图如图8-2所示。

1000

2

12

22

5

--发明家 权的第二批人是黑色人种--

public void method2() {

//产品类的公共妙招

      大伙儿儿也不 考虑另另三个多难题:另另三个多模块仅须要另另三个多工厂类,那么必要把它产生出来,使用静态的妙招就后会 了,根据否则 要求,大伙儿儿把上例中的AbstarctHumanFactory修改一下,类图如图8-3所示。

1

      另另三个多具体的创建工厂都非常简单,否则 ,可能性另另三个多系统复杂化化时工厂类也会相应变复杂化。场景类NvWa修改后的代码如代码清单8-19所示。

18

9

      每我各自 种(具体的产品类)都对应了另另三个多创建者,每个创建者都独立负责创建对应的产品对象,非常符合单一职责原则,按照否则 模式大伙儿儿来看代码变化。

    所有的人种定义完毕,下一步也不 定义另另三个多八卦炉,否则 烧制人类。大伙儿儿想象一下,女娲最可能性给八卦炉下达哪几个样的生产命令呢?应该是“给我生产出另另三个多黄色人种(YellowHuman类)”,而我太大 是“给我生产另另三个多会走、会跑、会说话、皮肤是黄色的人种”,可能性也不 的命令增加了交流的成本,作为另另三个多生产的管理者,否则我知道生产哪几个就后会 了,而不须要事物的具体信息。通过分析,大伙儿儿发现八卦炉生产人类的妙招输入参数类型应该是Human接口的实现类,这也解释了为哪几个类图上的AbstractHumanFactory抽象类中createHuman妙招的参数为Class类型。其源代码如代码清单8-5所示。

System.out.println("--发明家 权的第一批人是白色人种--");

6

6

18

19

19

12

9

21

System.out.println("\n--发明家 权的第二批人是黑色人种--");

1

37

36

17

25

8

}

blackHuman.talk();

19

      注意 抽象妙招中可能性不再须要传递相关参数了,可能性每另另三个多具体的工厂都可能性非常明确我各自 的职责:创建我各自 负责的产品类对象。

7

1

3

14

//一块儿把对象放上去缓存容器中

7

} catch (Exception e) {

9

9

      白色人种的创建工厂如代码清单8-18所示。

36

}

}

25

}

System.out.println("\n--发明家 权的第二批人是黑色人种--");

Human human=null;

}

}

13

public class YellowHumanFactory extends AbstractHumanFactory {

36

代码清单8-18 白色人种的创建类

2

5

图8-6 延迟初始化通用类图

      考虑到须要特征清晰,大伙儿儿就为每个产品定义另另三个多创造者,否则 由调用者我各自 去选者与哪个工厂妙招关联。大伙儿儿还是以女娲造人为例,每我各自 种都有另另三个多固定的八卦炉,分别发明家 权黑色人种、白色人种、黄色人种,修改后的类图如图8-4所示。

6

9

3

4

public void method1(){

Human blackHuman = HumanFactory.createHuman(BlackHuman.class);

13

}

return product;

}

}

private Singleton(){

22

31

14

product = new ConcreteProduct2();

1

31

37

代码清单8-19 场景类NvWa

System.out.println("人种生成错误!");

      注意,大伙儿儿在这里采用了JDK 1.5的新特征:泛型(Generic),通过定义泛型对createHuman的输入参数产生两层限制:

7

4

constructor.setAccessible(true);

product = new ConcreteProduct1();

Constructor constructor=cl.getDeclaredConstructor();

whiteHuman.talk();

21

2

//第三次造人,火候正正好,优品!黄色人种

      该通用代码是另另三个多比较实用、易扩展的框架,读者后会 根据实际项目须要进行扩展。

1

1

10

product = prMap.get(type);

18

      延迟加载框架是后会 扩展的,这个于限制某另另三个多产品类的最大实例化数量,后会 通过判断Map中已有的对象数量来实现,也不 的防止是非常有意义的,这个于JDBC连接数据库,都有要求设置另另三个多MaxConnections最大连接数量,该数量也不 内存中最大实例化的数量。

//业务逻辑防止

14

7

10

4

}

//设置无参构造是可访问的

代码清单8-14 简单工厂模式中的场景类

15

25

11

}

15

2

      具体如何产生另另三个多产品的对象,是由具体的工厂类实现的,如代码清单8-11所示。

      非常简单的类图,Singleton定义了另另三个多private的无参构造函数,目的是不允许通过new的妙招创建另另三个多对象,如代码清单8-20所示。

      Singleton保证只有通过正常的渠道建立另另三个多对象,那SingletonFactory如何建立另另三个多单例对象呢?答案是通过反射妙招创建,如代码清单8-21所示。

26

14

24

23

      具体的产品类也不 算是多个,都继承于抽象产品类,其源代码如代码清单8-9所示。

6

6

25

1

7

8

2

6

}

//女娲第二次造人,火候过足,又是次品,

}

public void method2() {

}

2

*/

      人种有了,八卦炉都有了,剩下的工作也不 女娲架构设计 黄土,否则 命令八卦炉开始生产,其过程如代码清单8-7所示。

35

11

35

18

15

2

      其次,工厂妙招模式的扩展性非常优秀。在增加产品类的情况下,否则我适当地修改具体的工厂类或扩展另另三个多工厂类,就后会 完成“拥抱变化”。这个于在大伙儿儿的例子中,须要增加另另三个多棕色人种,则只须要增加另另三个多BrownHuman类,工厂类我太大 任何修改就可完成系统扩展。

//产生另另三个多实例对象

16

35

27

12

yellowHuman.talk();

public class BlackHumanFactory extends AbstractHumanFactory {

4

20

20

public static void main(String[] args) {

      Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses。定义另另三个多用于创建对象的接口,让子类决定实例化哪另另三个多类。工厂妙招使另另三个多类的实例化延迟到其子类。

27

29

4

whiteHuman.getColor();

代码清单8-5 抽象人类创建工厂

} catch (Exception e) {

return new BlackHuman();

}

}

}

public class NvWa {

if(type.equals("Product1")){

34

20

      延迟加载还后会 使用在另另三个多对象初始化复杂化化的情况,这个于硬件访问,涉及多方面的交互,则后会 通过延迟加载降低对象的产生和销毁带来的复杂化性。

10

8

2

10

}

2

6

代码清单8-15 多工厂模式的抽象工厂类

5

3

* 继续业务防止

8

24

37

Human whiteHuman = (new WhiteHumanFactory()).createHuman();

11

2

图8-4 多个工厂类的类图

}

1

15

1

14

24

代码清单8-6 人类创建工厂

System.out.println("白色人种会说话,一般都有否则 单字节。");

      以上通过工厂妙招模式创建了另另三个多单例对象,该框架后会 继续扩展,在另另三个多项目中后会 产生另另三个多单例构造器,所有须要产生单例的类都遵循一定的规则(构造妙招是private),否则 通过扩展该框架,否则我输入另另三个多类型就后会 获得唯一的另另三个多实例。

}

8

      工厂妙招模式使用的频率非常高,在大伙儿儿日常的开发中总能见到它的身影。其定义为:

8

29

//声明阴阳八卦炉

17

12

15

5

      首先,良好的封装性,代码特征清晰。另另三个多对象创建是有条件约束的,如另另三个多调用者须要另另三个多具体的产品对象,否则我知道否则 产品的类名(或约束字符串)就后会 了,我太大 知道创建对象的艰辛过程,减少模块间的耦合。

3

3

5

public static Singleton getSingleton(){

26

代码清单8-17 黄色人种的创建类

public void doSomething(){

6

代码清单8-10 抽象工厂类

29

5

2

      当大伙儿儿在做另另三个多复杂化化的项目时,总爱会遇到初始化另另三个多对象很耗费精力的情况,所有的产品类都放上去另另三个多工厂妙招中进行初始化会使代码特征不清晰。这个于,另另三个多产品类有六个具体实现,每个实现类的初始化(不仅仅是new,初始化包括new另另三个多对象,并对对象设置一定的初始值)妙招都有相同,可能性写在另另三个多工厂妙招中,势必会意味着该妙招巨大无比,那怎办?

7

//女娲第一次造人,火候过低,过低产品

33

7

yellowHuman.getColor();

      运行结果那么地处变化,否则 大伙儿儿的类图变简单了,否则 调用者也比较简单,该模式是工厂妙招模式的弱化,可能性简单,太大被称为简单工厂模式(Simple Factory Pattern),也叫做静态工厂模式。在实际项目中,采用该妙招的案例还是比较多的,其缺点是工厂类的扩展比较困难,不符合开闭原则,但它仍然是另另三个多非常实用的设计模式。

public class Singleton {

3

8

      其中的“?”表示的是,否则我实现了Human接口的类都后会 作为参数,泛型是JDK 1.5中的另另三个多非常重要的新特征,它减少了对象间的转换,约束其输入参数类型,对Collection集合下的实现类都后会 定义泛型。有关泛型完全知识,请参考相关的Java语法文档。

1

      最后,工厂妙招模式是典型的解耦框架。高层模块值须要知道产品的抽象类,否则 的实现类都有用关心,符合迪米特原则,我不须要的就我太大 说去交流;也符合依赖倒转原则,只依赖产品类的抽象;当然也符合里氏替换原则,使用产品子类替换产品父类,没难题!

28

}

//女娲第二次造人,火候过足,又是次品,

25

return new WhiteHuman();

21

37

13

32

System.out.println("白色人种的皮肤颜色是白色的!");

9

5

3

4

22

11

10

12

System.out.println("\n--发明家 权的第三批人是黄色人种--");

图8-2 工厂妙招模式通用类图

}

AbstractHumanFactory YinYangLu = new HumanFactory();

}

代码清单8-20 单例类

3

37

Human human=null;

9

17

19

27

17

7

Class cl= Class.forName(Singleton.class.getName());

public class ProductFactory {

public static synchronized Product createProduct(String type) throws Exception{

抽象工厂类如代码清单8-15所示。

4

7

代码清单8-9 具体产品类

Human yellowHuman = HumanFactory.createHuman(YellowHuman.class);

try {

2

Human blackHuman = YinYangLu.createHuman(BlackHuman.class);

6

22

13

}

14

public void talk() {

4

      首先,工厂妙招模式是new另另三个多对象的替代品,太大在所有须要生成对象的地方都后会 使用,否则 须要慎重地考虑是算是要增加另另三个多工厂类进行管理,增加代码的复杂化度。

blackHuman.talk();

29

21

}

黄色人种会说话,一般说的都有双字节。

Product product=null;

1000

/*

图8-3 简单工厂模式类图

8

public static void main(String[] args) {

1

13

15

//获得无参构造

}

Human blackHuman = (new BlackHumanFactory()).createHuman();

1

16

Creator creator = new ConcreteCreator();

1000

10

16

32

7

public class Client {

5

23

13

8

34

21

3

10

11

18

24

      哇,人类的生产过程就展现出来了!否则 世界就热闹起来了,黑人、白人、黄人都开始活动了,这也正是大伙儿儿现在的真实世界。以上也不 工厂妙招模式(没错,对该次要有难题,请继续阅读下去)。

human = (Human)Class.forName(c.getName()).newInstance();

5

//定义另另三个多生产的人种

public class NvWa {

7

31

//产生另另三个多人种

Product product =null;

1

//异常防止

      再次,工厂妙招模式后会 用在异构项目中,这个于通过WebService与另另三个多非Java的项目交互,人太好WebService号称是后会 做到异构系统的同构化,否则 在实际的开发中,还是会碰到太大难题,如类型难题、WSDL文件的支持难题,等等,从WSDL中产生的对象都认为是另另三个多产品,否则 由另另三个多具体的工厂类进行管理,减少与外围系统的耦合。

22

public void getColor(){

      第7章讲述了单例模式以及扩展出的多例模式,否则 指出了单例和多例的否则 缺点,大伙儿儿是都有后会 采用工厂妙招模式实现单例模式的功能呢?单例模式的核心要求也不 在内存中只有另另三个多对象,通过工厂妙招模式也后会 只在内存中生产另另三个多对象。类图如图8-5所示。

      最后,后会 使用在测试驱动开发的框架下,这个于,测试另另三个多类A,就须要把与类A有关联关系的类B也一块儿产生出来,大伙儿儿后会 使用工厂妙招模式把类B虚拟出来,防止类A与类B的耦合。目前可能性JMock和EasyMock的诞生,该使用场景可能性弱化了,读者后会 在遇到此种情况时直接考虑使用JMock或EasyMock。

7

13

6

System.out.println("\n--发明家 权的第三批人是黄色人种--");

13

11

}else{

13

34

34

20

22

25

11

35

23

8

yellowHuman.getColor();

15

26

1

39

10

28

16

}

13

//业务逻辑防止

17

24

4

4

5

//定义另另三个多生产出的人种

38

Human whiteHuman = HumanFactory.createHuman(WhiteHuman.class);

public class SingletonFactory {

13

5

16

public abstract Human createHuman(Class<? extends Human> c);

}

}

4

12

1

3

public abstract Product createProduct(Class<? extends Product> c);

8

* 通常为String、Enum、Class等,当然也后会 为空

}

13

11

//业务防止

4

8

35

yellowHuman.getColor();

4

23

3

5

19

      再次,屏蔽产品类。否则 特点非常重要,产品类的实现如何变化,调用者都有须要关心,它只须要关心产品的接口,否则我接口保持不表,系统中的上层模块就我太大 说地处变化,可能性产品类的实例化工作是由工厂类负责,另另三个多产品对象具体由哪另另三个多产品生成是由工厂类决定的。在数据库开发中,大伙儿儿应该并能深刻体会到工厂妙招模式的好处:可能性使用JDBC连接数据库,数据库从MySql切换到Oracle,须要改动地方也不 切换一下驱动名称(前提条件是SQL得话是标准得话),否则 的都有须要修改,这是工厂妙招模式灵活性的另另三个多直接案例。

/*

}

      当然,在复杂化的应用中一般采用多工厂的妙招,否则 再增加另另三个多协调类,防止调用者与各个子工厂交流,协调类的作用是封装子工厂类,对高层模块提供统一的访问接口。

9

if(prMap.containsKey(type)){

1000

14

9

return new YellowHuman();

10

21

9

31

8

27

public static void main(String[] args) {

5

private static Singleton singleton;

16

public abstract class AbstractHumanFactory {

2

图8-5 工厂妙招模式替代单例模式类图

2

17

//不允许通过new产生另另三个多对象

} catch (Exception e) {

23

return singleton;

//第三次造人,火候正正好,优品!黄色人种

17

5

17

14

17

try {

3

public abstract Human createHuman();

16

6

黑人会说话,一般人听不懂。

6

6

      ProductFactory负责产品类对象的创建工作,否则 通过prMap变量产生另另三个多缓存,对须要再次被重用的对象保留,Product和ConcreteProduct是另另三个多示例代码,请参考代码清单8-8和8-9。ProductFactory如代码清单8-22所示。

24

3

9

20

12

28

}

18

*/

12

      在工厂妙招模式中,抽象产品类Product负责定义产品的共性,实现对事物最抽象定义;Creator为抽象创建类,也也不 抽象工厂,具体如何创建产品类是由具体的实现工厂ConcreteCreator完成的。工厂妙招模式的变种较多,大伙儿儿来看另另三个多比较实用的通用源码。

9

7

//异常防止

10

18

10

15

12

return human;

public class YellowHumanFactory extends AbstractHumanFactory {

yellowHuman.talk();

代码清单8-22 延迟加载的工厂类

8

}

//业务逻辑防止

14

12

3

3

18

5

6

33

12

4

23

* 创建另另三个多产品对象,其输入参数类型后会 自行设置

14

11

//女娲第二次造人,火候过足,又是次品,

3

}

9

黑色人种的创建工厂如代码清单8-16所示。

2

7

代码清单8-11 具体工厂类

public abstract class Product {

15

//抽象妙招

public static void main(String[] args) {

//女娲第一次造人,火候过低,过低产品

Human yellowHuman = (new YellowHumanFactory()).createHuman();

//第三次造人,火候前一天好,优品!黄色人种

public Product createProduct(Class<? extends Product> c) {

}else{

try {

System.out.println("--发明家 权的第一批人是白色人种--");

16

}

product = (Product)Class.forName(c.getName()).newInstance();

8

public abstract class Creator {

}

白色人种的皮肤颜色是白色的!

14

      目前女娲只有另另三个多八卦炉,人太好现了生产人类的妙招,如代码清单8-6所示。

blackHuman.talk();

28

blackHuman.getColor();

4

21

System.out.println("--发明家 权的第一批人是白色人种--");

17

18

public class ConcreteCreator extends Creator {

1

25

32

32

7

prMap.put(type,product);

--发明家 权的第一批人是白色人种--

5

29

11

Human yellowHuman = YinYangLu.createHuman(YellowHuman.class);

System.out.println("人种生成错误!");

代码清单8-12 场景类

黑色人种的皮肤颜色是黑色的!

6

15

16

4

15

20

whiteHuman.talk();

9

28

System.out.println("\n--发明家 权的第二批人是黑色人种--");

      工厂妙招模式在项目中使用得非常频繁,以至于太大代码中都包含工厂妙招模式。该模式几乎尽人皆知,但都有每我各自 都能用得好。熟能生巧,熟练掌握该模式,多思考工厂妙招如何应用,否则 工厂妙招模式还后会 算是则 模式混合使用(这个于模版妙招模式、单例模式、原型模式等),变化出无穷的优秀设计,这也正是软件设计和开发的乐趣所在。

      工厂妙招模式有太大扩展,否则 算是则 模式结合使用威力更大,下面将介绍并都有扩展。

10

10

33

黄色人种的皮肤颜色是黄色的!

34

11

5

14

20

--发明家 权的第三批人是黄色人种--

      抽象工厂类负责定义产品对象的产生,源代码如代码清单8-10所示。

5

1

      通过获得类构造器,否则 设置访问权限,生成另另三个多对象,否则 提供内部访问,保证内存中的对象唯一。当然,否则 类也后会 通过反射的妙招建立另另三个多单例对象,人太好那么,否则 另另三个多项目或团队是有章程和规范的,何况可能性提供了另另三个多获得单例对象的妙招,为哪几个须要重新创建另另三个多新对象呢?除非是人们作恶。

19

//可能性Map中可能性有否则 对象

14

singleton = (Singleton)constructor.newInstance();

21

public abstract void method2();

}

return product;

public Human createHuman(Class<? extends Human> c){

}

20

6

代码清单8-21 负责生成单例的工厂类

3

6

public Human createHuman() {

2

12

36

9

19

}

代码清单8-16 黑色人种的创建类

5

whiteHuman.talk();

7

}

10

whiteHuman.getColor();

static{

1

return human;

3

8

33

//女娲第一次造人,火候过低,过低产品

1

}

}

      黄色人种的创建工厂如代码清单8-17所示。

yellowHuman.talk();

human = (Human)Class.forName(c.getName()).newInstance();

40

      其次,须要灵活的、可扩展的框架时,后会 考虑采用工厂妙招模式。万物皆对象,那万物也就皆产品类,这个于须要设计另另三个多连接邮件服务器的框架,有并都有网络协议可供选者:POP3、IMAP、HTTP,大伙儿儿就后会 把这并都有连接妙招作为产品类,定义另另三个多接口如IConnectMail,否则 定义对邮件的操作妙招,另另三个多具体的产品类(也也不 连接妙招)进行不同的实现,再定义另另三个多工厂妙招,按照不同的传入条件,选者不同的连接妙招。那么设计,后会 做到完美的扩展,如否则 邮件服务器提供了WebService接口,很好,大伙儿儿否则我增加另另三个多产品类就后会 了。

8

whiteHuman.getColor();

} catch (Exception e) {

26

12

public class HumanFactory extends AbstractHumanFactory {

public class WhiteHuman implements Human {

1000

10

33

      大伙儿儿在类图中再加了AbstractHumanFactory抽象类,一块儿把createHuman妙招设置为静态类型,复杂化了类的创建过程,变更的源码仅仅是HumanFactory和NvWa类,HumanFactory如代码清单8-13所示。

代码清单8-7 女娲类

2

26

public static Human createHuman(Class<? extends Human> c){

//产生另另三个多人种

9

public Human createHuman() {

白色人种会说话,一般都有否则 单字节。

}

Product product = creator.createProduct(ConcreteProduct1.class);