设计模式之创建型模式

创建型模式主要是用于创建对象,主要分为5大类:工厂方法模式(factory method pattern)、抽象工厂模式(Abstract factory pattern)、单例模式(Singleton pattern)、建造者模式(Builder pattern)、原型模式(prototype pattern)。

 

一、工厂方法模式(factory method pattern)

  工厂方法模式主要分为三种:普通工厂模式、多工厂方法模式、静态工厂方法模式

  1、普通工厂模式:创建一个工厂类,为有共同接口的类创建对象;通过传入的值和工厂类的判断条件进行匹配,创建不同的对象。

    

//对象的共同接口
public interface Phone {
    
    void call();
}

public class MiPhone implements Phone{

    @Override
    public void call() {
        System.out.println("雷布斯为你打call,,,,");
        
    }

}

public class IPhone implements Phone {

    @Override
    public void call() {
        System.out.println("果粉为你打call。。。。。。。。");

    }

}

public class HuaWeiPhone implements Phone {

    @Override
    public void call() {
        System.out.println("华为海军为你打call!!!!");
    }

}


//对象的生产工厂
public class PhoneFactory {
    
    public Phone produce(String type){
        if("小米".equals(type)){
            return new MiPhone();
        }else if("华为".equals(type)){
            return new HuaWeiPhone();
        }else if("苹果".equals(type)){
            return new IPhone();
        }else {
            return null;
        }
    }

}

//测试类
public class FactoryMethodPatternTest {

    public static void main(String[] args) {
        
        PhoneFactory phoneFactory = new PhoneFactory();
        Phone xiaomi = phoneFactory.produce("小米");
        Phone huawei = phoneFactory.produce("华为");
        Phone pingguo = phoneFactory.produce("苹果");
        
        xiaomi.call();
        huawei.call();
        pingguo.call();
    }

}

 

 

  2、多工厂方法模式:对普通工厂方法模式进行改进,在普通工厂方法模式中,如果传递的字符串出错,则不能正确创建对象,而多个工厂方法模式是提供多个工厂方法,直接调用不同的方法来创建不同的对象,这样不容易出错。

  

/**
*只需要将工厂方法和调用方法修改一下
*/

//多方法对象的生产工厂
public class PhoneFactory {
    
    public Phone produceMiPhone(){
            return new MiPhone();
    }
    
    public Phone produceHuaweiPhone(){
        return new HuaWeiPhone();
    }
    
    public Phone produceIPhone(){
        return new IPhone();
    }
    
}


//测试类
public class FactoryMethodPatternTest {

    public static void main(String[] args) {
        
        PhoneFactory phoneFactory = new PhoneFactory();
        Phone xiaomi = phoneFactory.produceMiPhone();
        Phone huawei = phoneFactory.produceHuaweiPhone();
        Phone pingguo = phoneFactory.produceIPhone();
        
        xiaomi.call();
        huawei.call();
        pingguo.call();
    }

}

 

  

  3、静态工厂方法模式:将上面的多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可。

//静态方法对象的生产工厂
public class PhoneFactory {
    
    public static Phone produceMiPhone(){
            return new MiPhone();
    }
    
    public static Phone produceHuaweiPhone(){
        return new HuaWeiPhone();
    }
    
    public static Phone produceIPhone(){
        return new IPhone();
    }
    
}


//测试类
public class FactoryMethodPatternTest {

    public static void main(String[] args) {
        
        Phone xiaomi = PhoneFactory.produceMiPhone();
        Phone huawei = PhoneFactory.produceHuaweiPhone();
        Phone pingguo = PhoneFactory.produceIPhone();
        
        xiaomi.call();
        huawei.call();
        pingguo.call();
    }

}

 

 

 

二、抽象工厂模式(Abstract factory pattern)

  上面的工厂方法模式如果要扩展就必须修改代码,这样就违反了开闭原则。抽象工厂模式将对象的生产工厂也进行抽象,方便程序扩展。

//对象生产工厂接口
public interface PhoneFactory {

    Phone produce();
}

public class MiPhoneFactory implements PhoneFactory{
    
    @Override
    public Phone produce() {
        return new  MiPhone();
    }
    
}

public class HuaWeiPhoneFactory implements PhoneFactory{
    
    @Override
    public Phone produce() {
        return new HuaWeiPhone();
    }

}


public class IPhoneFactory implements PhoneFactory {

    @Override
    public Phone produce() {
        return new IPhone();
    }

}


//测试类
public class AbstractFactoryPatternTest {

    public static void main(String[] args) {
        
        PhoneFactory miPhoneFactory = new MiPhoneFactory();
        PhoneFactory huaWeiFactory = new HuaWeiPhoneFactory();
        PhoneFactory iphoneFactory = new IPhoneFactory();
        
        Phone miPhone = miPhoneFactory.produce();
        Phone huaWeiPhone = huaWeiFactory.produce();
        Phone iPhone = iphoneFactory.produce();
        
        miPhone.call();
        huaWeiPhone.call();
        iPhone.call();
        
    }

}

 

 

三、单例模式(Singleton pattern):

  单例模式主要分为:饿汉式、懒汉式、双重检测锁、静态内部类、枚举类

  1、饿汉式:顾名思义就是很饥饿,还不需要该对象的时候就直接创建该对象。

  

//饿汉单例模式
public class Singleton {
    
    //在类的初始化阶段就直接创建好对象
    private static Singleton instance = new Singleton();
    
    //私有化构造方法,保证无法创建更多对象,该对象只能通过getInstance方法来进行获取
    private Singleton(){}
    
    public static Singleton getInstance(){
        return instance;
    }
}

 

 

  2、懒汉式:需要用到该对象的时候才会区创建对象

 

//懒汉单例模式,只在第一次需要的时候才会创建对象,有线程安全问题
public class Singleton2 {
    
    private static Singleton2 instance = null;
    
    private Singleton2 (){}
    
    public static Singleton2 getInstance(){
        if( instance == null ){
            instance = new Singleton2();
        }
        
        return instance;
    }

}

 

 

//懒汉单例模式,只在第一次需要的时候才会创建对象,没有线程安全问题,但是每次取对象的时候都需要获取锁,影响效率
public class Singleton3 {
    
    private static Singleton3 instance = null;
    
    private Singleton3 (){}
    
    public static synchronized Singleton3 getInstance(){
        if( instance == null ){
            instance = new Singleton3();
        }
        
        return instance;
    }

}

 

 

  3、双重检测锁模式:在懒汉式基础上改进,效率比懒汉式要高。

//双重检测锁单例模式,是线程安全的,并且只有前几次需要获取锁,效率比饿汉线程安全模式高。
//但是由于jvm底层的原因,在创建对象的时候有可能出现指令重排,后面的线程获取了还未初始化的对象,并且去执行对应的方法,这样就会出现问题。
//可以通过volatile 来防止指令重排
public class Singleton4 {
    
    private static Singleton4 instance = null;
    
    private Singleton4 (){}
    
    public static Singleton4 getInstance(){
        if( instance == null ){
            synchronized (Singleton4.class) {
                if( instance == null ){
                    instance = new Singleton4();
                }
            }
        }
        
        return instance;
    }

}

 

 

  3.1、补充

 

//这种方式貌似能够解决双重检测锁的问题
public class Singleton7 {
    
    private static Singleton7 instance = null;
    
    private Singleton7 (){}
    
    private static synchronized void createSingleton7(){
        instance  = new Singleton7();
    }
    
    public static Singleton7 getInstance(){
        if( instance == null ){
            synchronized (Singleton7.class) {
                if( instance == null ){
                    createSingleton7();
                }
            }
        }
        
        return instance;
    }

}

 

 

  4、静态内部类模式:运用静态内部类的特性来构造单例

//静态内部类单例模式,这种方式线程安全并且是懒加载
public class Singleton5 {
    
    private Singleton5 (){}
    
    public static class SingletonContainer{
        private static Singleton5 instance = new Singleton5();
    }
    
    public static Singleton5 getInstance(){
        return SingletonContainer.instance;
    }

}

 

  

  5、枚举类:枚举类的元素本身就是单例对象。

//枚举类的元素就是单例的,并且无线程安全问题。在序列化和反序列化之后也能保证单例
public enum Singleton6 {
    
    INSTANCE;
    
    //需要执行的操作
    public void doSomeThing(){}

}

 

 

 

四、建造者模式(Builder pattern)

  建造者模式又名创建者模式,是将一个复杂对象的构建过程与它的表示分离,从而使得相同的构建过程可以创建不同的表示;创建者模式隐藏了复杂对象的创建过程,它把复杂对象的构建加以抽象,通过子类继承或者重载的方式,动态的创建具有复合属性的对象。

与工厂模式的区别是:建造者模式更加关注与零件装配的顺序。

  主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。

public class Car {
    
    private String Body;
    
    private String wheel;

    public String getBody() {
        return Body;
    }

    public void setBody(String body) {
        Body = body;
    }

    public String getWheel() {
        return wheel;
    }

    public void setWheel(String wheel) {
        this.wheel = wheel;
    }

    @Override
    public String toString() {
        return "Car [Body=" + Body + ", wheel=" + wheel + "]";
    }
    
}

 

 

public interface Builder {
    
    void buildBody();
    
    void buildWheel();

    Car getCar();
}


public class BenzBuilder implements Builder {
    
    private String body;
    private String wheel;
    
    @Override
    public void buildBody() {
        this.body = "奔驰车身";
    }

    @Override
    public void buildWheel() {
        this.wheel = "奔驰轮子";
    }

    @Override
    public Car getCar() {
        Car car = new Car();
        car.setBody(body);
        car.setWheel(wheel);
        return car;
    }

}

 

 

//对车辆进行组装
public class Director {

    private Builder builder;
    
    public Director(Builder builder){
        this.builder = builder;
    }
    
    public void setBuilder(Builder builder){
        this.builder = builder;
    }
    
    //组装车辆
    public Car constructCar(){
        builder.buildBody();
        builder.buildWheel();
        builder.buildWheel();
        builder.buildWheel();
        builder.buildWheel();
        
        return builder.getCar();
    } 
    
}


//测试
public class BuilderTest {

    public static void main(String[] args) {
        
        Builder benzBuilder = new BenzBuilder();
        Director director2= new Director(benzBuilder);
        Car car2 = director2.constructCar();
        System.out.println(car2);
    }

}

 

 

五、原型模式(prototype pattern)

  原型模式虽然是创建型的模式,但是与工程模式没有关系,从名字即可看出,该模式的思想就是将一个对象作为原型,对其进行复制、克隆,产生一个和原对象类似的新对象。直接创建对象的代价比较大时,则采用这种模式。

  浅复制:将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的。

  深复制:将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。简单来说,就是深复制进行了。

  java中通过clone来实现对象的浅复制,一个原型类,只需要实现Cloneable接口,覆写clone方法就可以实现浅复制。通过实现Serializable 接口然后通过序列化和反序列化进行深度复制。

 

public class Prototype implements Cloneable, Serializable {

    private static final long serialVersionUID = 1L;
    
    private String name;
    
    private List<String> list;
    
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<String> getList() {
        return list;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
    
    protected 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();  
    }

    @Override
    public String toString() {
        return "Prototype [name=" + name + ", list=" + list + "]";
    }

}

 

 

public class PrototypeTest {

    public static void main(String[] args) throws Exception {
        Prototype p = new Prototype();
        p.setName("a");
        List<String> list = new ArrayList<>();
        list.add("b");
        p.setList(list);
        System.out.println(p);
        
        //浅复制
        Prototype p1 = (Prototype)p.clone();
        System.out.println(p1);
        
        //深复制
        Prototype p2 = (Prototype)p.deepClone();
        System.out.println(p2);
        
        System.out.println("------------------------------");    
        
        //修改原型的值,发现复制后的对象的值也被修改了
        list.add("c");
        p.setName("A");
        p.setList(list);
        System.out.println(p);
        System.out.println(p1);
        System.out.println(p2);
        
    }

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  

posted @ 2018-09-29 17:12  KyleInJava  阅读(226)  评论(0编辑  收藏  举报