设计模式-5种创建型

设计模式系列博文:
1. 设计模式-6大设计原则
2. 设计模式-5种创建型
3. 设计模式-7种结构型
4. 设计模式-11种行为型

1.单例模式

单例模式的实现,一共有5种方式:
1. 饿汉式
2. 懒汉式
3. 双重锁定式
4. 枚举式
5. 静态内部类式
此处仅以最常见的双重锁定式为例!
适用于内存中只有唯一实例,避免频繁创建销毁。
注意:易导致内存泄露!不利于mock测试!

代码

package base.designpattern.creational;

/**
 * 单例模式
 * <p>
 * 案例:臣子觐见皇帝
 * Created by yutianran on 16/7/1.
 */
public class SingletonPattern {

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            //每次都有一个臣子觐见皇帝
            Emperor emperor = Emperor.getInstance();
            Minister minister = new Minister();
            minister.see(emperor);
        }
    }

    //皇帝
    public static class Emperor {
        private static Emperor instance;

        //禁止外部创建
        private Emperor() {
        }

        //双重锁定式
        public static Emperor getInstance() {
            if (null == instance) {
                synchronized (Emperor.class) {
                    if (null == instance) {
                        instance = new Emperor();
                    }
                }
            }
            return instance;
        }
    }

    //臣子
    public static class Minister {

        public void see(Emperor emperor) {
            System.out.println("臣子:" + this + "\t觐见皇帝:" + emperor);
        }
    }
}

输出:
这里写图片描述


2.原型模式

内存二进制流的拷贝,优于直接new对象
使用时必须注意浅拷贝和深拷贝!
除了基本类型/String/包装类,其余的都是浅拷贝,只传递引用,没有传递对象,此时若要深拷贝,需要让其引用的对象也实现Cloneable接口并复写clone方法
关于Java-克隆

代码:

package base.designpattern.creational;


/**
 * 原型模式
 * <p>
 * 案例:盗版书
 * Created by yutianran on 16/7/1.
 */
public class PrototypePattern {

    public static void main(String[] args) {
        //正版书
        Book src = new Book("设计模式之禅");
        src.setPreface(new Preface("这是一本介绍设计模式的书"));

        //盗版书
        Book pirate = src.clone();
        //修改书名
        pirate.setName("设计模式之禅-Clone");
        //修改序言
        Preface preface = pirate.getPreface();
        preface.setDesc("这是一本介绍设计模式的书-Clone");

        System.out.println("正版书:" + src.toString());
        System.out.println("盗版书:" + pirate.toString());
    }

    //书
    public static class Book implements Cloneable {
        private String name;//书名
        private Preface preface;//序言

        public Book(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

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

        public Preface getPreface() {
            return preface;
        }

        public void setPreface(Preface preface) {
            this.preface = preface;
        }


        @Override
        protected Book clone() {
            Book clone = null;
            try {
                clone = (Book) super.clone();
                //这里必须同时调用引用对象的clone方法
                clone.preface = this.preface.clone();
            } catch (CloneNotSupportedException e) {
                System.out.println("克隆出错:" + e.getMessage());
            }
            return clone;
        }

        @Override
        public String toString() {
            return "Book{" +
                    "name='" + name + '\'' +
                    ", preface=" + preface +
                    '}';
        }
    }

    //序言
    public static class Preface implements Cloneable {
        private String desc;//介绍

        public Preface(String desc) {
            this.desc = desc;
        }

        public String getDesc() {
            return desc;
        }

        public void setDesc(String desc) {
            this.desc = desc;
        }

        @Override
        protected Preface clone() {
            Preface clone = null;
            try {
                clone = (Preface) super.clone();
            } catch (CloneNotSupportedException e) {
                System.out.println("克隆出错:" + e.getMessage());
            }
            return clone;
        }

        @Override
        public String toString() {
            return "Preface{" +
                    "desc='" + desc + '\'' +
                    '}';
        }
    }
}

输出:
这里写图片描述


3.建造者模式

链式创建,不必在构造方法中传入过多参数,或构造之后分开set
与set方法的区别是每次设置参数都返回builder自身,之后再根据builder构造对象
当建造过程很繁琐时,建议增加Director-导演类,封装建造过程

代码:

package base.designpattern.creational;

/**
 * 建造者模式
 * <p>
 * 案例:创建网络请求
 * Created by yutianran on 16/7/1.
 */
public class BuilderPattern {

    public static void main(String[] args) {
        String url = "http://baidu.com";
        Request request = new Request.Builder()
                .url(url)
                .method("POST")
                .headers("Content-Type:application/json;charset=UTF-8")
                .body("{\"userId\":145}")
                .tag(url)
                .build();
        System.out.println("网络请求:" + request.toString());
    }

    //网络请求类
    public static class Request {
        private String url;
        private String method;
        private String headers;
        private String body;
        private String tag;

        public Request(Builder builder) {
            if (null == builder.url) {
                throw new IllegalArgumentException("url == null");
            }
            this.url = builder.url;
            this.method = builder.method;
            this.headers = builder.headers;
            this.body = builder.body;
            this.tag = builder.tag;
        }

        public String getUrl() {
            return url;
        }

        public String getMethod() {
            return method;
        }

        public String getHeaders() {
            return headers;
        }

        public String getBody() {
            return body;
        }

        public String getTag() {
            return tag;
        }

        @Override
        public String toString() {
            return "Request{" +
                    "url='" + url + '\'' +
                    ", methodB='" + method + '\'' +
                    ", headers='" + headers + '\'' +
                    ", body='" + body + '\'' +
                    ", tag='" + tag + '\'' +
                    '}';
        }

        //建造者
        public static class Builder {
            private String url;
            private String method;
            private String headers;
            private String body;
            private String tag;

            public Builder url(String url) {
                this.url = url;
                return this;
            }

            public Builder method(String method) {
                this.method = method;
                return this;
            }

            public Builder headers(String headers) {
                this.headers = headers;
                return this;
            }

            public Builder body(String body) {
                this.body = body;
                return this;
            }

            public Builder tag(String tag) {
                this.tag = tag;
                return this;
            }

            public Request build() {
                return new Request(this);
            }
        }
    }
}

输出:
这里写图片描述


4.静态工厂模式

静态工厂类似于一个管理类,决定创建出哪一种产品类的实例。
也可以不使用反射,而用枚举,那样的话,性能会好一点,但是却不能对修改关闭了,每添加一个新的产品类,都需要修改工厂类

代码:

package base.designpattern.creational;

/**
 * 简单工厂模式
 * <p>
 * Created by yutianran on 16/7/1.
 */
public class SimpleFactoryPattern {

    public static void main(String args[]) {
        IProduct product = SimpleFactory.produce(ProductA.class);
        product.method();
    }

    //抽象产品
    public static abstract class IProduct {
        public abstract void method();
    }

    //具体产品A
    public static class ProductA extends IProduct {
        @Override
        public void method() {
            System.out.println("I'm ProductA!");
        }
    }

    //具体产品B
    public static class ProductB extends IProduct {
        @Override
        public void method() {
            System.out.println("I'm ProductB!");
        }
    }

    //静态工厂
    public static class SimpleFactory {

        public static <T extends IProduct> T produce(Class<T> clazz) {
            IProduct human = null;
            try {
                human = (IProduct) Class.forName(clazz.getName()).newInstance();
            } catch (Exception e) {
                System.out.println("创建错误:" + e.getMessage());
            }
            return (T) human;
        }
    }


}

输出:
这里写图片描述


5.工厂方法模式

不只是产品有抽象父类,工厂也有抽象父类!
将产品和工厂的依赖关系抽象化,不再依赖具体的实现类,方便拓展。
一个具体产品对应一个具体工厂。

代码:

package base.designpattern.creational;

/**
 * 工厂方法模式
 * <p>
 * Created by yutianran on 16/7/1.
 */
public class FactoryMethodPattern {

    public static void main(String[] args) {
        AbstractFactory factoryA = new ConcreteFactoryA();
        AbstractProduct product = factoryA.produce();
        product.method();
    }

    //抽象产品
    public static abstract class AbstractProduct {
        public abstract void method();
    }

    //抽象工厂
    public static abstract class AbstractFactory {
        public abstract AbstractProduct produce();
    }


    //具体产品
    public static class ProductA extends AbstractProduct {
        @Override
        public void method() {
            System.out.println("I'm ProductA!");
        }
    }

    public static class ProductB extends AbstractProduct {
        @Override
        public void method() {
            System.out.println("I'm ProductB!");
        }
    }

    //具体工厂
    public static class ConcreteFactoryA extends AbstractFactory {
        @Override
        public ProductA produce() {
            return new ProductA();
        }
    }

    public static class ConcreteFactoryB extends AbstractFactory {
        @Override
        public ProductB produce() {
            return new ProductB();
        }
    }


}

输出:
这里写图片描述


6.抽象工厂模式

工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。
工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。

代码:

package base.designpattern.creational;

/**
 * 抽象工厂模式
 * <p>
 * Created by yutianran on 16/7/1.
 */
public class AbstractFactoryPattern {

    public static void main(String[] args) {
        AbstractFactory factory = new ConcreteFactory1();
        AbstractProductA producta1 = factory.produceA();
        AbstractProductB productb1 = factory.produceB();
        producta1.methodA();
        productb1.methodB();
    }

    //抽象产品族
    public static abstract class AbstractProductA {
        public abstract void methodA();
    }

    public static abstract class AbstractProductB {
        public abstract void methodB();
    }

    //抽象工厂
    public static abstract class AbstractFactory {
        public abstract AbstractProductA produceA();

        public abstract AbstractProductB produceB();
    }

    //具体产品
    public static class ProductA1 extends AbstractProductA {
        @Override
        public void methodA() {
            System.out.println("Im ProductA1!");
        }
    }

    public static class ProductA2 extends AbstractProductA {
        @Override
        public void methodA() {
            System.out.println("Im ProductA2!");
        }
    }

    public static class ProductB1 extends AbstractProductB {
        @Override
        public void methodB() {
            System.out.println("Im ProductB1!");
        }
    }

    public static class ProductB2 extends AbstractProductB {
        @Override
        public void methodB() {
            System.out.println("Im ProductB2!");
        }
    }

    //具体工厂
    public static class ConcreteFactory1 extends AbstractFactory {
        @Override
        public AbstractProductA produceA() {
            return new ProductA1();
        }

        @Override
        public AbstractProductB produceB() {
            return new ProductB1();
        }
    }

    public static class ConcreteFactory2 extends AbstractFactory {
        @Override
        public AbstractProductA produceA() {
            return new ProductA2();
        }

        @Override
        public AbstractProductB produceB() {
            return new ProductB2();
        }
    }
}

输出:
这里写图片描述


一般喜欢将简单工厂模式归入工厂方法模式之中,但我觉得工厂方法模式其实和抽象工厂模式更像一点。

菜鸟一枚,水平有限,欢迎大家指出博文中的不足之处,小鱼将不胜感激!@qq:630709658

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值