设计模式精髓篇之创建型

说明

借鉴的JDK中的优秀源码来帮助自己理解设计模式,另外一方面还能帮助自己深入的了解JDK。类型中包含的模式可能不齐全,我只详细的描述了一些相对重要的设计模式。

类之间的关系

设计模式主要是基于类之间的关系来设计的。先了解类之间的关系和表示形式是很有必要的。
继承关系
继承
实现关系
实现
依赖关系
类A使用到了另一个类B,或者对象方法中返回B类对象
依赖
关联关系
类A的成员变量是类B,体现的是两个类之间语义级别的一种强依赖关系
关联
聚合关系
聚合是关联关系的一种特例,它体现的是整体与部分的关系,即has-a的关系。整体与部分可分。如公司与员工。
聚合
组合关系
组合也是关联关系的一种特例,它体现的是一种contains-a的关系,这种关系比聚合更强。整体与部分是不可分的关系。如人体与心脏。
组合

对象的四种生成方式

1.使用new来创建。

Object object=new Object();//此种方法将会调用类的构造函数。

2.java的反射机制

///假设你已经创建了一个类Test

//方式一,使用Class类,会调用类的构造函数,方式一内部的实现还是调用方式二的getConstructor方法来实现的
Class class=Class.forName("包名.Test");
Test test1=(Test)class.newInstance();//创建了test对象,由object对象转换为test对象
//方式二使用Constructor,会调用类的构造函数
Constructor<Test>cons=Test.class.getConstructor();
Test test2=cons.newInstance();

3.clone方法

///////假设你已经创建了一个类Test,其中Test类需要实现Cloneable接口,复写clone方法。具体怎么复写,需要看你是深复制还是浅复制.
Test test=new Test();//之前已经创建了一个对象.
Test test1=test.clone();//创建了一个新的对象,此时不在调用构造函数,并且test1指向的新堆的内存空间.

4.反序列化方法

///当我们序列化和反序列化一个对象,jvm会给我们创建一个单独的对象。类需要实现序列化接口
ObjectInputStream in = new ObjectInputStream(new FileInputStream("test.obj"));
Test test= (Test) in.readObject();
创建型模式

提供了创建什么(what),由谁来创建(who),以及何时(when)来创建

单例模式

目标: 向整个系统提供一个唯一的对象实例。
why-思考: 如何确保要生成的类的对象只有一个?当需要使用使用该对象时是使用时先生成还是创建该类的时候生成?如何确保多处同时需要访问唯一对象时,怎么确保原子性?
How-思考: 将构造方法私有化,并在内中方法生成对象,外部将不能生成对象了;需要查看具体的情况,看资源使用率和线程安全性,资源使用率高的是懒加载,线程安全性好的创建类时便生成对象;使用多线程间锁的机制。
JDK中的示例:

//java.lang.Runtime类
public class Runtime {
    private Runtime() {}//私有的构造方法
    //Runtime类的私有静态实例
    private static Runtime currentRuntime = new Runtime();
    //获得静态实例的唯一方法
    public static Runtime getRuntime() {
        return currentRuntime;
    }
}
工厂三大类模式

包括静态工厂、工厂模式、抽象工厂。工厂相关的模式主要包含要创建的对象类(产品类)和主导有创建功能的类(工厂类)。
目标:

*静态工厂*,因为要创建的类型较少,可根据类型进行创建对象,并且要将对象的实例化过程进行封装,外部创建对象调用的方式更清晰。
*工厂模式*,因为要创建的类型的对象较多,并且可能需要扩展对象的类型,让子类去决定实例化那个对象。重点在如何抽取要创建的对象类的共同点上。
**抽象工厂**,因为要创建的对象的包含的组别很多,不同的组包括不同的类型,为创建一组相关或相互依赖的对象。重点在如何抽取要创建的对象类的共同点上和抽象化工厂类上。

why—思考:

*静态工厂*,工厂类如何做到根据不同的参数类型,输出不同的对象?
*工厂模式*,如果对象的参数类型过多,并且或者需要不定期扩展不同的对象时,工厂类该怎样设计?
**抽象工厂**,要创建的对象是一组相关的或相互依赖,并且组内不同的对象类型可以不同,工厂模式又该怎么设计?

How-思考:

*静态工厂*,通过添加静态生成对象的函数,根据不同的参数,使用不同的实例化对象的方法。
*工厂模式*,提取出要创建的不同类型的对象的公共方法并封装成接口,在具体的对象中实现该接口。
**抽象工厂**,工厂模式的扩展,因为组包含一组包含多个不同类型的对象。

JDK中的示例:

//静态工厂java.lang.Class
//根据不同的类名来创建对象
public static Class<?> forName(String className)
                throws ClassNotFoundException {
Class<?> caller = Reflection.getCallerClass();
return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
    }

//工厂, Iterator类产品类
//说明,因为Iterator包含很多种类,有LinkList中的ListItr、ArrayList中的ListItr、Vector中的ListItr(都是内部类),以后可能还需要扩展其他集合类的Iterator。
//提取出要创建的不同类型的对象的公共部分并封装成接口。
interface Iterator<E> 
{ 
 boolean hasNext();
 E next();
}
//LinkList中的ListItr、ArrayList中的ListItr、Vector中的ListItr根据自身特征分别实现接口。
//工厂类Collection(LinkList、ArrayList、Vector)中创建产品。
Iterator<Object> it=list.iterator();

//抽象工厂 java.sql.Connection
//说明,抽象工厂重点在产品类的抽象和工厂类的抽象。
 interface Connection{
 //工厂要创建的产品组:Clob ,Blob ,NClob ,Statement(每个都是抽象的产品)
 Clob createClob() throws SQLException;
 Blob createBlob() throws SQLException;
 NClob createNClob() throws SQLException;
 Statement createStatement() throws SQLException;
 ......
 }
 //抽象产品Statement由很多产品对象的公共部分组成接口
 interface Statement{
  boolean execute(String sql) throws SQLException;
  ResultSet getResultSet() throws SQLException;
  .....
 }
 //具体的创建对象可以实现Statement功能形成不同的对象。
 //Clob ,Blob ,NClob同是抽象产品可以具体化到很多产品
 //大工厂实现Connection接口将对象组合。
 /工厂模式可以看出抽象工厂的组内只有一种类型。
建造者模式

目标: 将一个复杂对象的构建和它的表示分离。重点在抽象出类的Build类。
why-思考: 怎么将一个复杂的类构建尼?构建后怎么达到分离尼?
How-思考: 类的构建主要是对类的成员变量进行重新设置,因为每个成员变量可以取不同的值,但是最后都是需要设置的,所以对每个成员变量可以抽取出各自的的设置部分,从而将类的构建分离出。
正常示例:

//JDK中没有找到好的示例,列举两种方式。
//方式一
public class Test
//复杂类
{
    private String part1;
    private String part2;
    private String part3;
    ......
}
//分离Build,抽象化,重点
interface Build{
public interface ICarBuilder
{
    public void buildpart1();
    public void buildpart2();
    public void buildpart3();
    Test buildTest();
}
//ConBuild实现Build接口
conBuild.buildpart1();
......
Test test=conBuild.buildTest();
}
//方式二
//将Build封装在要创建的对象内部。
Class Test{
    private String part1;
    private String part2;
    private String part3;
    ......
    private ClassTest(Build build){
     this.part1=build.part1;
     ......
    }
    public static Class Build{
     private String part1;
     private String part2;
     private String part3;
     public Builder part1(string val){
            this.part1= val;
            return this;
        }
     public Builder part2(string val){
            this.part2= val;
            return this;
        }
        ......
     public Test build(){
       return new Build(this);
     }
    }
}
//通过分离者Build来创建对象实例
Test test=new Test.Build().part1("1").part2("2").part3("3").build();
//方式二相对方式一扩展性更弱,好处是易于代码的管理
原型模式

目标: 用原型实例大量的复制创建新的对象。重点是需要大量创建新对象。
JDK中的示例:

接口Cloneable的用法
感想
对创建型模式的感想(到模式中去)
1.明确项目中要创建的对象是否只需要一个。或者是否需要大批复制创建。
2.要创建的对象是否很复杂,复杂体现在该对象对应的类的成员变量是否包含多个,并且成员变量多变,赋值过程分离出来是否更好。
3.要创建的对象的类型是否很多,学会抽象出共同部分,当类型多,或者多变的情况,一定首先想到要面向接口编程,抽取共同部分,然后**分角色**考虑问题是工厂者,对象产品或者建造者。

----分角色思考问题很重要,抽取共同部分也很重要!!!-------
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值