Contents
  1. 1. 单例模式
  2. 2. 工厂模式
  3. 3. 原型模式
    1. 3.1. 相同对象的浅复制
    2. 3.2. 相似对象的浅复制
    3. 3.3. 验证浅复制
    4. 3.4. 深复制
  4. 4. 建造者模式

参考源码:
https://github.com/huangzhenshi/DesignPattern

单例模式

实现在系统中,最多只有1个这个类,比如datasourse这样的类,从而节省系统资源。
通过private构造方法避免new对象,并且只提供一个getInstance的方法、和设置静态成员变量的方法,来控制只有1个实例。

  • 懒汉式(不安全,有概率生成多个):在需要的时候去生成初始化一个静态的成员变量

    public class LazySingleton {
    private LazySingleton() {}
    private static LazySingleton instance = null;
    public static LazySingleton getInstance() {
    if (null == instance) {
    instance = new LazySingleton();
    }
    return instance;
    }
    }
  • 饿汉式(类的初始化期就生成一个实例,保证线程安全)

    private HungerSinleton(){}
    private static HungerSinleton instance = new HungerSinleton();
    public static HungerSinleton getInstance() {
    return instance;
    }
  • 双重锁式:节省不必要的内存的同时确保了只有一个

    private SyncSingleton(){}
    private static SyncSingleton instance = null;
    public static SyncSingleton getInstance() {
    if (null == instance) {
    synchronized(SyncSingleton.class) {
    if (null == instance) {
    instance = new SyncSingleton();
    }
    }
    }
    return instance;
    }

工厂模式

为了解决创建对象不直接new,而是通过工厂类来获取,优点如下:

  1. 类的获取就实现了解耦,以后要换类,直接改工厂,就完事了。
  2. 对类做封装,比如通用构造参数的添加,可以在工厂里做了
  3. 隐藏类的全名
  4. 在创建对象的时候做一些通用的事情(比如输出日志)
  • 简单工厂模式:通过类名字符串,写死获取对应的对象。这样可扩展性很差。

    public class Factory {
    public ProductI create(String productName) {
    switch (productName) {
    case "A":
    return new ProductA();
    case "B":
    return new ProductB();
    default:
    return null;
    }
    }
    }
  • 工厂方法模式
    简单模式所有的产品都依赖工厂类的一个方法,修改之后可能导致其他产品出问题。工厂方法模式就是工厂类作为接口,每个不同的产品由不同的实现工厂类去生产,这样要新增修改、删除某个产品,其他的产品丝毫不受影响

    public interface FactoryI {
    // 工厂的目的是为了生产产品
    public ProductI create();
    }
    public class FactoryA implements FactoryI {
    @Override
    public ProductI create() {
    return new ProductA();
    }
    }
    public class FactoryB implements FactoryI {
    @Override
    public ProductI create() {
    return new ProductB();
    }
    }
    public class Client {
    public static void main(String[] args) {
    FactoryI factoryA = new FactoryA();
    ProductI productA = factoryA.create();
    productA.productName();
    //
    FactoryI factoryB = new FactoryB();
    ProductI productB = factoryB.create();
    productB.productName();
    }
    }
  • 抽象工厂模式
    就是在工程方法模式里面生产配套相关的多个产品啊。
    比如PC厂商接口,下面有Dell厂商、HP厂商、IBM厂商,Dell实现工厂类生产Dell笔记本、台式机、键盘、鼠标等产品。

原型模式

http://blog.csdn.net/jason0539/article/details/23158081

  • 性能提升
    使用原型模式创建对象比直接new一个对象在性能上要好的多,因为Object类的clone方法是一个本地方法,它直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显。

  • 简化创建
    使用原型模式的另一个好处是简化对象的创建,实现类似模板功能,比如某对象创建后进行一些列加工成为了模板典型的对象,其他人直接clone()这个模板即可,简化了创建后各种加工配置等操作。

注意事项:

  1. 一般原型对象都是抽象类,不希望Client直接去创建它,而是通过他的子类间接的去创建它
  2. Cloneable接口是个空接口,所以clone()可以叫任何名字,核心是里面的super.clone();
  3. 非基本类型和String类型的成员变量,默认都是浅复制,每个拷贝的成员变量都是指向同一个堆内存,除非进行深复制
  4. 突破构造函数的束缚,会突破单例模式的束缚

相同对象的浅复制

public abstract class Prototype implements Cloneable {
public Prototype clone(){
Prototype prototype = null;
try{
prototype = (Prototype)super.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
return prototype;
}
}
public class ConcretePrototype extends Prototype{
public void show(){
System.out.println("原型模式实现类");
}
}
public class Client {
public static void main(String[] args){
ConcretePrototype cp = new ConcretePrototype();
for(int i=0; i< 10; i++){
ConcretePrototype clonecp = (ConcretePrototype)cp.clone();
clonecp.show();
}
}
}

相似对象的浅复制

把不一样的方法做成抽象方法,让不同的子类按照各自的逻辑去重写,这样公用相同的方法,也支持不一样

public abstract class Prototype implements Cloneable {
public Prototype clone(){
Prototype prototype = null;
try{
prototype = (Prototype)super.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
return prototype;
}
public void doCommon(){
System.out.println("Prototype doing Common");
}
public abstract void doSpecial();
}
public class ConcretePrototypeA extends Prototype{
@Override
public void doSpecial() {
System.out.println("ConcretePrototypeA doing Special");
}
}
public class ConcretePrototypeB extends Prototype{
@Override
public void doSpecial() {
System.out.println("ConcretePrototypeB doing Special");
}
}
public class Client {
public static void main(String[] args){
ConcretePrototypeA cpa = new ConcretePrototypeA();
cpa.doSpecial();
cpa.doCommon();
ConcretePrototypeB cpb = new ConcretePrototypeB();
cpb.doSpecial();
cpb.doCommon();
}
}

验证浅复制

public abstract class Prototype implements Cloneable {
private List<String> list=new ArrayList();
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
public Prototype clone(){
Prototype prototype = null;
try{
prototype = (Prototype)super.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
return prototype;
}
}
public class Client {
public static void main(String[] args){
ConcretePrototype cp = new ConcretePrototype();
cp.getList().add("huangzhenshi");
System.out.println(cp.getList().get(0));
ConcretePrototype clonecp = (ConcretePrototype)cp.clone();
System.out.println(clonecp.getList().size());
//对原型实现类对象的成员变量list进行修改
cp.getList().add("huangxiaozhen");
//结果拷贝类的成员变量list的size也发生了改变,输出是2
System.out.println(clonecp.getList().size());
}
}

深复制

结果操作原型类的成员变量list的时候,拷贝类的成员变量不会收到影响

public class Prototype implements Cloneable {
protected ArrayList list = new ArrayList();
public Prototype clone(){
Prototype prototype = null;
try{
prototype = (Prototype)super.clone();
prototype.list = (ArrayList) this.list.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
return prototype;
}
}
public class Client {
public static void main(String[] args){
ConcretePrototypeA cpa = new ConcretePrototypeA();
ConcretePrototypeA cpa_clone=(ConcretePrototypeA) cpa.clone();
System.out.println(cpa.list.size());
System.out.println(cpa_clone.list.size());
cpa.list.add("hzs");
System.out.println(cpa.list.size());
System.out.println(cpa_clone.list.size());
}
}

建造者模式

http://www.runoob.com/design-pattern/builder-pattern.html

使用多个简单的对象一步一步构建成一个复杂的对象。扩展性好,但是要求组成元素有共同属性。

  • 扩展性好:新增一种大类,或者老品类里面添加一个新子类都很容易扩展;不添加新元素,老元素不同搭配形成新套餐也很容易扩展

  • 理解案例:肯德基套餐经常在变化(搭配扩展性),有时候也添加新类型(比如牛肉卷、粥类),有时候老类型里面添加新品牌(比如 饮料之前是 百事 和Coke,现在添加 红牛进来),但是商品属性都一样:price、name。

  • 元素类有3个层级:最上层是抽象的商品接口,第二层是大类(大类可能有某共同性),第三层是具体的商品

//所有商品 拥有相同的属性:price 和 name
public interface Item {
public String name();
public float price();
}
// 核心类Builder,不同的套餐分别装配不同的元素
public class MealBuilder {
public Meal prepareVegMeal (){
Meal meal = new Meal();
meal.addItem(new VegBurger());
meal.addItem(new Coke());
return meal;
}
public Meal prepareNonVegMeal (){
Meal meal = new Meal();
meal.addItem(new ChickenBurger());
meal.addItem(new Pepsi());
return meal;
}
}
Contents
  1. 1. 单例模式
  2. 2. 工厂模式
  3. 3. 原型模式
    1. 3.1. 相同对象的浅复制
    2. 3.2. 相似对象的浅复制
    3. 3.3. 验证浅复制
    4. 3.4. 深复制
  4. 4. 建造者模式