zoukankan      html  css  js  c++  java
  • 设计模式(一)创建型模式

      创建型模式的主要关注点是“怎样创建对象?”,它的主要特点是“将对象的创建与使用分离”。这样可以降低系统的耦合度,使用者不需要关注对象的创建细节。这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。

    1.单例模式(Singleton)

      指一个类只有一个实例,且该类能自行创建这个实例的一种模式。

      关键代码:

    构造函数是私有的。

      单例模式的优点:

    1.单例模式可以保证内存里只有一个实例,减少了内存的开销。
    2.可以避免对资源的多重占用。
    3.单例模式设置全局访问点,可以优化和共享资源的访问。

      懒汉式单例

      该模式的特点是类加载时没有生成单例,只有当第一次调用 getlnstance 方法时才去创建这个单例。

    public class LazySingleton {
        private static volatile LazySingleton instance = null;    //保证 instance 在所有线程中同步
        private LazySingleton() {
        }    //private 避免类在外部被实例化
        public static synchronized LazySingleton getInstance() {
            //getInstance 方法前加同步
            if (instance == null) {
                instance = new LazySingleton();
            }
            return instance;
        }
    }
    View Code

      饿汉式单例

      该模式的特点是类一旦加载就创建一个单例,保证在调用 getInstance 方法之前单例已经存在了,线程安全。

    public class HungrySingleton {
        private static final HungrySingleton instance = new HungrySingleton();
        private HungrySingleton() {
        }
        public static HungrySingleton getInstance() {
            return instance;
        }
    }
    View Code

    2.原型模式(Prototype)

      用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。

      关键代码:

    JAVA 继承 Cloneable,重写 clone(),实现克隆操作 

      原型模式的优点:

    Java 自带的原型模式基于内存二进制流的复制,在性能上比直接 new 一个对象更加优良。

      浅拷贝

      创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址

    //具体原型类
    class Realizetype implements Cloneable {
        Realizetype() {
            System.out.println("具体原型创建成功!");
        }
        public Object clone() throws CloneNotSupportedException {
            System.out.println("具体原型复制成功!");
            return (Realizetype) super.clone();
        }
    }
    //原型模式的测试类
    public class PrototypeTest {
        public static void main(String[] args) throws CloneNotSupportedException {
            Realizetype obj1 = new Realizetype();
            Realizetype obj2 = (Realizetype) obj1.clone();
            System.out.println("obj1==obj2?" + (obj1 == obj2));
        }
    }
    View Code

      深拷贝

      创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。

      1.实现Cloneable接口

    public class Demo implements Cloneable {
     
        private String name;
        private String value;
        private DemoInternal demoInternal;
     
        /*省略getter和setter方法*/
     
        @Override
        public Demo clone() {
            Demo demo = null;
            try {
                demo = (Demo) super.clone(); //浅复制
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            demo.demoInternal = demoInternal.clone(); //深度复制
            return demo;
        }
    }
    View Code

      2.实现Serializable接口

    public class CloneUtils {
        @SuppressWarnings("unchecked")
        public static <T extends Serializable> T clone(T obj) {
            T cloneObj = null;
            try {
                // 写入字节流
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                ObjectOutputStream obs = new ObjectOutputStream(out);
                obs.writeObject(obj);
                obs.close();
     
                // 分配内存,写入原始对象,生成新对象
                ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray());
                ObjectInputStream ois = new ObjectInputStream(ios);
                // 返回生成的新对象
                cloneObj = (T) ois.readObject();
                ois.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return cloneObj;
        }
    View Code

    3.工厂方法模式(Factory Method)

      定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行

      工厂方法模式的优点:

    1.用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程。
    2.灵活性增强,对于新产品的创建,只需多写一个相应的工厂类。
    3.典型的解耦框架。高层模块只需要知道产品的抽象类,无须关心其他实现类,满足迪米特法则、依赖倒置原则和里氏替换原则。

      工厂方法模式的主要角色如下:

    抽象工厂(Abstract Factory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法 newProduct() 来创建产品。
    具体工厂(ConcreteFactory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建。
    抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能。
    具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。

       AbstractFactory类:生产不同产品的工厂的抽象类

    public interface AbstractFactory {
        Phone makePhone();
    }
    View Code

      XiaoMiFactory类:生产小米手机的工厂(ConcreteFactory1)

    public class XiaoMiFactory implements AbstractFactory{
        @Override
        public Phone makePhone() {
            return new MiPhone();
        }
    }
    View Code

      AppleFactory类:生产苹果手机的工厂(ConcreteFactory2)

    public class AppleFactory implements AbstractFactory {
        @Override
        public Phone makePhone() {
            return new IPhone();
        }
    }
    View Code

      对象创建:生产手机

    public class Demo {
        public static void main(String[] arg) {
            AbstractFactory miFactory = new XiaoMiFactory();
            AbstractFactory appleFactory = new AppleFactory();
            miFactory.makePhone();            // make xiaomi phone!
            appleFactory.makePhone();        // make iphone!
        }
    }
    View Code

    4.抽象工厂模式(AbstractFactory)

      是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。

      抽象工厂模式的主要角色如下:

    抽象工厂(Abstract Factory):提供了创建产品的接口,它包含多个创建产品的方法 newProduct(),可以创建多个不同等级的产品。
    具体工厂(Concrete Factory):主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建。
    抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品。
    具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间是多对一的关系。

       PC类:定义PC产品的接口(AbstractPC)

    public interface PC {
        void make();
    }
    View Code

      MiPC类:定义小米电脑产品(MIPC)

    public class MiPC implements PC {
        public MiPC() {
            this.make();
        }
        @Override
        public void make() {
            // TODO Auto-generated method stub
            System.out.println("make xiaomi PC!");
        }
    }
    View Code

      MAC类:定义苹果电脑产品(MAC)

    public class MAC implements PC {
        public MAC() {
            this.make();
        }
        @Override
        public void make() {
            // TODO Auto-generated method stub
            System.out.println("make MAC!");
        }
    }
    View Code

      AbstractFactory类:增加PC产品制造接口

    public interface AbstractFactory {
        Phone makePhone();
        PC makePC();
    }
    View Code

      XiaoMiFactory类:增加小米PC的制造(ConcreteFactory1)

    public class XiaoMiFactory implements AbstractFactory{
        @Override
        public Phone makePhone() {
            return new MiPhone();
        }
        @Override
        public PC makePC() {
            return new MiPC();
        }
    }
    View Code

      AppleFactory类:增加苹果PC的制造(ConcreteFactory2)

    public class AppleFactory implements AbstractFactory {
        @Override
        public Phone makePhone() {
            return new IPhone();
        }
        @Override
        public PC makePC() {
            return new MAC();
        }
    }
    View Code

      对象创建:生产手机、电脑

    public class Demo {
        public static void main(String[] arg) {
            AbstractFactory miFactory = new XiaoMiFactory();
            AbstractFactory appleFactory = new AppleFactory();
            miFactory.makePhone();            // make xiaomi phone!
            miFactory.makePC();                // make xiaomi PC!
            appleFactory.makePhone();        // make iphone!
            appleFactory.makePC();            // make MAC!
        }
    }
    View Code

    5.建造者模式(Builder)

      指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。

      该模式的主要优点如下:

    1.封装性好,构建和表示分离。
    2.扩展性好,各个具体的建造者相互独立,有利于系统的解耦。
    3.客户端不必知道产品内部组成的细节,建造者可以对创建过程逐步细化,而不对其它模块产生任何影响,便于控制细节风险。

       建造者(Builder)模式的主要角色如下:

    产品角色(Product):它是包含多个组成部件的复杂对象,由具体建造者来创建其各个零部件。
    抽象建造者(Builder):它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法 getResult()。
    具体建造者(Concrete Builder):实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。
    指挥者(Director):它调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息。

       建造者:

    abstract class Builder {
        //地基
        abstract void bulidA();
        //钢筋工程
        abstract void bulidB();
        //铺电线
        abstract void bulidC();
        //粉刷
        abstract void bulidD();
        //完工-获取产品
        abstract Product getProduct();
    }
    View Code

      产品:

    @Data
    public class Product {
        private String buildA;
        private String buildB;
        private String buildC;
        private String buildD;
    }
    View Code

      具体建造者:

    public class ConcreteBuilder extends Builder{
        private Product product;
        public ConcreteBuilder() {
            product = new Product();
        }
        @Override
        void bulidA() {
            product.setBuildA("地基");
        }
        @Override
        void bulidB() {
            product.setBuildB("钢筋工程");
        }
        @Override
        void bulidC() {
            product.setBuildC("铺电线");
        }
        @Override
        void bulidD() {
            product.setBuildD("粉刷");
        }
        @Override
        Product getProduct() {
            return product;
        }
    }
    View Code

      指挥者:

    public class Director {
        //指挥工人按顺序造房
        public Product create(Builder builder) {
            builder.bulidA();
            builder.bulidB();
            builder.bulidC();
            builder.bulidD();
            return builder.getProduct();
        }
    }
    View Code

      演示:

    public class Demo{
        public static void main(String[] args) {
            Director director = new Director();
            Product create = director.create(new ConcreteBuilder());
            System.out.println(create.toString());
        }
    }
    View Code

    参照:http://c.biancheng.net/view/1320.html

  • 相关阅读:
    WebGL编程指南案例解析之绘制一个点
    在pixi中使用你的自定义着色器
    一个关于运维人员做事的很好的case,拿出来和大家共勉
    2015小目标
    在工作中修行
    ROW模式的SQL无法正常同步的问题总结
    从周末教儿子学溜冰联想到带人
    group_concat函数导致的主从同步异常
    招聘运维工程师
    一个锁的奇怪问题分析总结
  • 原文地址:https://www.cnblogs.com/ryjJava/p/14391144.html
Copyright © 2011-2022 走看看