版权声明:本文为博主原创文章,转载注明出处http://blog.csdn.net/u013142781/article/details/50821155
1.单例模式(Singleton Pattern)
public class Singleton {
private static final Singleton singleton = new Singleton();
//限制产生多个对象
private Singleton(){
}
//通过该方法获得实例对象
public static Singleton getSingleton(){
return singleton;
}
//类中其他方法,尽量是static
public static void doSomething(){
}
}
优点:
1.在单例模式中,活动的单例只有一个实例,对单例类的所有实例化得到的都是相同的一个实例。这样就 防止其它对象对自己的实例化,确保所有的对象都访问一个实例
2.单例模式具有一定的伸缩性,类自己来控制实例化进程,类就在改变实例化进程上有相应的伸缩性。
3.提供了对唯一实例的受控访问。
4.由于在系统内存中只存在一个对象,因此可以 节约系统资源,当 需要频繁创建和销毁的对象时单例模式无疑可以提高系统的性能。
5.允许可变数目的实例。
6.避免对共享资源的多重占用。
缺点:
1.不适用于变化的对象,如果同一类型的对象总是要在不同的用例场景发生变化,单例就会引起数据的错误,不能保存彼此的状态。
2.由于单利模式中没有抽象层,因此单例类的扩展有很大的困难。
3.单例类的职责过重,在一定程度上违背了“单一职责原则”。
4.滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;如果实例化的对象长时间不被利用,系统会认为是垃圾而被回收,这将导致对象状态的丢失。
使用注意事项:
1.使用时不能用反射模式创建单例,否则会实例化一个新的对象
2.使用懒单例模式时注意线程安全问题
3.单例模式和懒单例模式构造方法都是私有的,因而是不能被继承的,有些单例模式可以被继承(如登记式模式)
● 多线程的线程池的设计一般也是采用单例模式,这是由于线程池要方便对池中的线程进行控制
线程不安全实例:
public class Singleton {
private static Singleton singleton = null;
//限制产生多个对象
private Singleton(){
}
//通过该方法获得实例对象
public static Singleton getSingleton(){
if(singleton == null){
singleton = new Singleton();
}
return singleton;
}
}
解决办法:
在getSingleton方法前加synchronized关键字,也可以在getSingleton方法内增加synchronized来实现。最优的办法是如通用代码那样写。
2.工厂模式
工厂方法模式工厂方法模式分为三种:普通工厂模式、多个工厂方法模式和静态工厂方法模式。
普通工厂模式
普通工厂模式就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建。
具体工厂类代码:
package com.mode.create;
public interface MyInterface{
public void print();
}
package com.mode.create;
public class MyClassOne implements MyInterface {
@Override
public void print() {
System.out.println("MyClassOne");
}
}
package com.mode.create;
public class MyClassTwo implements MyInterface {
@Override
public void print() {
System.out.println("MyClassTwo");
}
}
package com.mode.create;
public class MyFactory {
public MyInterface produce(String type) {
if ("One".equals(type)) {
return new MyClassOne();
} else if ("Two".equals(type)) {
return new MyClassTwo();
} else {
System.out.println("没有要找的类型");
return null;
}
}
}
package com.mode.create;
public class FactoryTest {
public static void main(String[] args){
MyFactory factory = new MyFactory();
MyInterface myi = factory.produce("One");
myi.print();
}
}
直接看代码吧,,我们修改MyFactory和FactoryTest如下:
package com.mode.create;
public class MyFactory {
public MyInterface produceOne() {
return new MyClassOne();
}
public MyInterface produceTwo() {
return new MyClassTwo();
}
}
package com.mode.create;
public class FactoryTest {
public static void main(String[] args){
MyFactory factory = new MyFactory();
MyInterface myi = factory.produceOne();
myi.print();
}
}
总结:多个工厂方法模式,是对普通工厂方法模式的改进,多个工厂方法模式就是提供多个工厂方法,分别创建对象。
静态工厂方法模式
直接看代码吧,我们修改MyFactory和FactoryTest如下:
package com.mode.create;
public class MyFactory {
public static MyInterface produceOne() {
return new MyClassOne();
}
public static MyInterface produceTwo() {
return new MyClassTwo();
}
}
package com.mode.create;
public class FactoryTest {
public static void main(String[] args){
MyInterface myi = MyFactory.produceOne();
myi.print();
}
}
总结:静态工厂方法模式,将上面的多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可。
抽象工厂模式
工厂方法模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了闭包原则。
为解决这个问题,我们来看看抽象工厂模式:创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。
这样就符合闭包原则了。
下面来看看代码:
MyInterface、MyClassOne、MyClassTwo不变。
新增如下接口和类:
package com.mode.create;
public interface Provider {
public MyInterface produce();
}
package com.mode.create;
public class MyFactoryOne implements Provider {
@Override
public MyInterface produce() {
return new MyClassOne();
}
}
package com.mode.create;
public class MyFactoryTwo implements Provider {
@Override
public MyInterface produce() {
return new MyClassTwo();
}
}
package com.mode.create;
public class FactoryTest {
public static void main(String[] args){
Provider provider = new MyFactoryOne();
MyInterface myi = provider.produce();
myi.print();
}
}
总结:抽象工厂模式就是创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。
建造者模式
建造者模式:是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
字面看来非常抽象,实际上它也十分抽象!!!!
建造者模式通常包括下面几个角色:
(1) Builder:给出一个抽象接口,以规范产品对象的各个组成成分的建造。这个接口规定要实现复杂对象的哪些部分的创建,并不涉及具体的对象部件的创建。
(2) ConcreteBuilder:实现Builder接口,针对不同的商业逻辑,具体化复杂对象的各部分的创建。 在建造过程完成后,提供产品的实例。
(3)Director:调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建。
(4)Product:要创建的复杂对象。
在游戏开发中建造小人是经常的事了,要求是:小人必须包括头,身体和脚。
下面我们看看如下代码:
Product(要创建的复杂对象。):
package com.mode.create;
public class Person {
private String head;
private String body;
private String foot;
public String getHead() {
return head;
}
public void setHead(String head) {
this.head = head;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getFoot() {
return foot;
}
public void setFoot(String foot) {
this.foot = foot;
}
}
Builder(给出一个抽象接口,以规范产品对象的各个组成成分的建造。这个接口规定要实现复杂对象的哪些部分的创建,并不涉及具体的对象部件的创建。):
package com.mode.create;
public interface PersonBuilder {
void buildHead();
void buildBody();
void buildFoot();
Person buildPerson();
}
ConcreteBuilder(实现Builder接口,针对不同的商业逻辑,具体化复杂对象的各部分的创建。 在建造过程完成后,提供产品的实例。):
package com.mode.create;
public class ManBuilder implements PersonBuilder {
Person person;
public ManBuilder() {
person = new Person();
}
public void buildBody() {
person.setBody("建造男人的身体");
}
public void buildFoot() {
person.setFoot("建造男人的脚");
}
public void buildHead() {
person.setHead("建造男人的头");
}
public Person buildPerson() {
return person;
}
}
Director(调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建。):
package com.mode.create;
public class PersonDirector {
public Person constructPerson(PersonBuilder pb) {
pb.buildHead();
pb.buildBody();
pb.buildFoot();
return pb.buildPerson();
}
}
测试类:
package com.mode.create;
public class Test {
public static void main(String[] args) {
PersonDirector pd = new PersonDirector();
Person person = pd.constructPerson(new ManBuilder());
System.out.println(person.getBody());
System.out.println(person.getFoot());
System.out.println(person.getHead());
}
}
总结:建造者模式是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
原型模式
该模式的思想就是将一个对象作为原型,对其进行复制、克隆,产生一个和原对象类似的新对象。
说道复制对象,我将结合对象的浅复制和深复制来说一下,首先需要了解对象深、浅复制的概念:
浅复制:将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的。
深复制: 将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。简单来说,就是深复制进行了完全彻底的复制,而浅复制不彻底。
package com.mode.create;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class Prototype implements Cloneable, Serializable {
private static final long serialVersionUID = 1L;
private int base;
private Integer obj;
/* 浅复制 */
public Object clone() throws CloneNotSupportedException {
// 因为Cloneable接口是个空接口,你可以任意定义实现类的方法名
// 如cloneA或者cloneB,因为此处的重点是super.clone()这句话
// super.clone()调用的是Object的clone()方法
// 而在Object类中,clone()是native(本地方法)的
Prototype proto = (Prototype) super.clone();
return proto;
}
/* 深复制 */
public Object deepClone() throws IOException, ClassNotFoundException {
/* 写入当前对象的二进制流 */
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
/* 读出二进制流产生的新对象 */
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}
public int getBase() {
return base;
}
public void setBase(int base) {
this.base = base;
}
public Integer getObj() {
return obj;
}
public void setObj(Integer obj) {
this.obj = obj;
}
}
测试类:
package com.mode.create;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws CloneNotSupportedException,
ClassNotFoundException, IOException {
Prototype prototype = new Prototype();
prototype.setBase(1);
prototype.setObj(new Integer(2));
/* 浅复制 */
Prototype prototype1 = (Prototype) prototype.clone();
/* 深复制 */
Prototype prototype2 = (Prototype) prototype.deepClone();
System.out.println(prototype1.getObj()==prototype1.getObj());
System.out.println(prototype1.getObj()==prototype2.getObj());
}
}