Java设计模式----创建者模式

1.设计模式概述

设计模式不是语法规定,就是提高代码可复用性、可维护性、可读性、稳健性以及安全性的解决方案。是前辈对代码开发经验的总结,解决问题的一系列套路

面向对象设计原则的实际运用,是对类的封装、继承、多态以及类的关联关系和组合关系的充分理解。

一个设计模式:

  • 模式名称

  • 问题

  • 解决方案

  • 效果

2.OOP七大原则

OOP:Object Oriented Programming 面向对象的程序设计

开闭原则:

对扩展开放、对修改关闭(核心就是不改变源代码)

一个实体允许在不改变它的源代码情况下变更它的行为(就是说可以扩展它的行为,但是最好不要修改)

当一个对象已经有两个行为了,可以通过建设新的类,让这个类继承新类进而实现行为的扩展(这里指的继承也只是一种实现扩展的方式),而不是通过修改原来的类代码进行增加新的行为。

里氏替换原则:

继承必须确保父类所拥有的性质在子类中仍然成立(子类可以扩展父类的功能,但是不要改版父类原有的功能)

子类继承父类时,可以添加新的方法完成新增功能外,尽量不要重写父类的方法

依赖倒置原则:

高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。

面向接口编程(降低耦合性),不要面向实现编程。

抽象不依赖具体、具体依赖抽象

单一职责原则:

控制类的粒度大小、将对象解耦、提高其内聚性

一个类不应该承担太多的职责,一个类只用做好一件事就可以

接口隔离原则:

要为各个类建立它们需要的专用接口

迪米特原则:

只和直接朋友交谈,不和“陌生人”说话。放在框架里就是不跨层进行交流

合成复用原则:

尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现

3.创建者模式

主要是创建对象

(1)单例模式Singleton

概念:

提供了一种访问对象的唯一方式,保证一个类只有这一个实例。单例的关键就是:私有化构造函数

不能通过构造函数生成对象

例子:

这是饿汉式单例,直接一上来就创建对象

public class SingleObject {
 
   //创建 SingleObject 的一个对象
   private static SingleObject instance = new SingleObject();
 
   //让构造函数为 private,这样该类就不会被实例化
   private SingleObject(){}
 
   //获取唯一可用的对象
   public static SingleObject getInstance(){
      return instance;
   }
 
   public void showMessage(){
      System.out.println("Hello World!");
   }
}
public class SingletonPatternDemo {
   public static void main(String[] args) {
 
      //不合法的构造函数
      //编译时错误:构造函数 SingleObject() 是不可见的
      //SingleObject object = new SingleObject();
 
      //获取唯一可用的对象
      SingleObject object = SingleObject.getInstance();
 
      //显示消息
      object.showMessage();
   }
}

测试单例:这个类只有一个实例

public class SingletonTest {
​
    public static void main(String[] args) {
        HungrySingle hungrySingle1=HungrySingle.getInstance();
        HungrySingle hungrySingle2=HungrySingle.getInstance();
        hungrySingle1.setName("11");
        hungrySingle2.setName("22");
        hungrySingle1.showName();   //22
        hungrySingle2.showName();   //22
        if(hungrySingle1==hungrySingle2){
            System.out.println("same");  // same
        }else{
            System.out.println("different");
        }
    }
}

实现方式:

饿汉式:

是否 Lazy 初始化:

是否多线程安全:

实现难度:

描述:这种方式比较常用,但容易产生垃圾对象。 优点:没有加锁,执行效率会提高。 缺点:类加载时就初始化,浪费内存。

/**
 * 饿汉式单例
 * 上来就创建对象
 * 如果对象中有占用比较大内存的数组之类的
 * 就会比较耗内存
 * 所以出现了:懒汉式单例用的时候创建对象
 */
public class HungrySingle {
    private HungrySingle() {
    }
​
    private final static HungrySingle HUNGRY_SINGLE=new HungrySingle();
    public static HungrySingle getInstance(){
        return HUNGRY_SINGLE;
    }
}

懒汉式:

一般用的是懒汉式单例中线程安全的部分即加锁

线程不安全:没加锁

是否 Lazy 初始化:是

是否多线程安全:否

实现难度:易

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

线程安全:加锁

是否 Lazy 初始化:

是否多线程安全:

实现难度:

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

DCL单例(double-checked locking)双重检验计加锁模式

是否 Lazy 初始化:

是否多线程安全:

实现难度:较复杂

public class Singleton {  
    private volatile static Singleton singleton;  
    private Singleton (){}  
    public static Singleton getSingleton() {  
    if (singleton == null) {  
        synchronized (Singleton.class) {  
            if (singleton == null) {  
                singleton = new Singleton();  
            }  
        }  
    }  
    return singleton;  
    }  
}

④静态内部类

是Singleton类中还存在一个静态类SingletonHolder,在静态类SingletonHolder中采用的是饿汉式单例,但是与饿汉式单例不同的是:Singleton类被装载了但是instance不一定被初始化(而饿汉式单例是singleton类被装载了instance一定被初始化了)

是否 Lazy 初始化:

是否多线程安全:

实现难度:一般

public class Singleton {  
    private static class SingletonHolder {  
    private static final Singleton INSTANCE = new Singleton();  
    }  
    private Singleton (){}  
    public static final Singleton getInstance() {  
        return SingletonHolder.INSTANCE;  
    }  
}

⑤枚举

是否 Lazy 初始化:

是否多线程安全:

实现难度:

public enum Singleton {  
    INSTANCE;  
    public void whateverMethod() {  
    }  
}

应用:

数据库连接池、线程池、windows任务管理器、windows的回收站、操作系统的文件管理器

(2)工厂模式Factory

概念:

实现创建者和使用者的分离(使用者不需要去直接创建对象(new),而是让工厂去创建对象,使用者直接去工产拿对象)

满足开闭原则、依赖倒装原则、迪米特法则

核心原则:实例化对象不使用new,用工厂方法代替(比如安卓中的viewmodel就是用factory实例化的 ) 将调用者和实现类进行解耦的操作

实现方式:

①简单(静态)工产模式

只有一个工产

对于car而言,有两个实现类carImpl和carImpl1;

如果consumer需要这两个车,按照原有的方式就是new这两个实现类

//用原始的new方法
//        Car car=new CarImpl();
//        Car car1=new CarImpl1();

如果按照简单工产模式:

就是新建一个CarFactory,在这个factory中创建两个car对象,在consumer中利用factory生成对象

/**8
 * 简单工厂模式(静态工产模式)
 * 不满足开闭原则
 * 增加一个新的产品,必须修改代码
 */
public class CarFactory {
    //如果需要增加一个车的话,那就需要修改代码逻辑
    // (不满足开闭原则)
    //可以进行一次优化:可以直接getCar1(),但是这个方法
    //也会出现需要修改这个类
    public static Car getCar(String car){
        if(car.equals("car")){
            return new CarImpl();
        }else if(car.equals("car1")){
            return new CarImpl1();
        }else{
            return null;
        }
    }
}
//用工厂模式创建
Car car=CarFactory.getCar("car");
Car car1=CarFactory.getCar("car1");
car.name();
car1.name();

但是简单工产模式存在一个比较大的问题就是:

不满足开闭原则,当需要增加一个car时需要去修改原有的代码

但是从代码复杂度、管理角度而言,simpleFactory是有很大优势的,所以在实际运用的角度而言一般选择simple

②工产方法模式

有多个工产,满足开闭原则

因为简单工产模式不满足开闭原则,进而提出工产方法模式解决这个问题

工产方法实际上就是每个车都有一个车工产,car1有一个Car1Factory,car2有一个Car2

Fartory.....如果需要增加car的话,就不需要修改原有的代码,直接增加一个Car3Factory就可

/**
 * 工厂方法模式
 */
public interface CarFactory {
    Car getCar();
}
/**
 * 每个车都有自己的工产
 * 如果该需要增加车那直接增加那个车的工产就行
 */
public class Car1Factory implements CarFactory {
    @Override
    public Car getCar() {
        return new CarImpl1();
    }
}
public class Consumer {
    public static void main(String[] args) {
        Car car1=new Car1Factory().getCar();
    }
}

但是这个实现方式,导致代码量增多,代码管理难度也加大,在实际运用中不是很常用

(3)抽象工产模式

概念:

一个超级工产创建其他的工厂

产品族:

Java设计模式----创建者模式_第1张图片

 

抽象工产扩充产品族难,扩充产品等级简单

代码实现:

产品:

phone:

/**8
 * 手机产品接口
 */
public interface IphoneProduct {
​
    void start();
    void shut();
    void callup();
    void send();
}
package com.study.shejiPattern.factory.abstract1;
//小米手机
public class XiaomiPhone implements IphoneProduct {
    @Override
    public void start() {
        System.out.println("开启小米手机");
    }
​
    @Override
    public void shut() {
        System.out.println("小米手机");
    }
​
    @Override
    public void callup() {
        System.out.println("小米手机");
    }
​
    @Override
    public void send() {
        System.out.println("小米手机");
    }
}


package com.study.shejiPattern.factory.abstract1;
​
public class HuaWeiPhone implements IphoneProduct {
    @Override
    public void start() {
        System.out.println("huawei");
    }
​
    @Override
    public void shut() {
        System.out.println("huawei");
    }
​
    @Override
    public void callup() {
        System.out.println("huawei");
    }
​
    @Override
    public void send() {
        System.out.println("huawei");
    }
}

router:

/**
 * 路由器产品
 */
public interface IRouterProduct {
    void start();
    void shut();
    void openWifi();
    void setting();
}

huawei、xiaomi与上面的一致

工产:

xiaomi和huawei的工产都需要实现这个抽象类工产

package com.study.shejiPattern.factory.abstract1;
//抽象产品工产
public interface IProductFactory {
    //生产手机
    IphoneProduct iphoneProduct();
​
    //生产路由器
    IRouterProduct routeProduct();
}
package com.study.shejiPattern.factory.abstract1;
​
public class HuaweiFactory implements IProductFactory {
    @Override
    public IphoneProduct iphoneProduct() {
        return new HuaWeiPhone();
    }
​
    @Override
    public IRouterProduct routeProduct() {
        return new HuweiRouter();
    }
}
package com.study.shejiPattern.factory.abstract1;
​
/**
 * 小米生产
 */
public class XiaomiFactory implements IProductFactory {
    @Override
    public IphoneProduct iphoneProduct() {
        return new XiaomiPhone();
    }
​
    @Override
    public IRouterProduct routeProduct() {
        return new XiaomiRouter();
    }
}

client:

package com.study.shejiPattern.factory.abstract1;
​
public class Client {
    public static void main(String[] args) {
        System.out.println("----------xiaomi---");
        XiaomiFactory xiaomiFactory=new XiaomiFactory();
        IphoneProduct iphoneProduct=xiaomiFactory.iphoneProduct();
        iphoneProduct.start();
        IRouterProduct xiaomaR=xiaomiFactory.routeProduct();
        xiaomaR.openWifi();
        System.out.println("----------huawei---");
        HuaweiFactory huaweiFactory=new HuaweiFactory();
        IphoneProduct huawei=huaweiFactory.iphoneProduct();
        huawei.start();
        IRouterProduct huaweiR=huaweiFactory.routeProduct();
        huaweiR.openWifi();
    }
}

当需要增加一个产品时,会需要改很多代码

扩充产品族:难

Java设计模式----创建者模式_第2张图片

扩充产品等级:简单

Java设计模式----创建者模式_第3张图片

(4)建造者模式

概念:

建造复杂对象 将复杂对象的构建与他的表示分离

应用场景:需要生产的产品对象有复杂的内部结构,但是这些产品具有共性,指挥可以创建不用的产品

Java设计模式----创建者模式_第4张图片

 

代码实现:

/**
 * 抽象的建造者
 * 产品建造的方法 ----具体产品的建造方法去Worker中实现
 *
 */
public abstract class Builder {
    abstract void buildA();
    abstract void buildB();
​
    abstract Product getProduct();
​
}
package com.study.shejiPattern.builder.demo;
​
/**
 * 具体的建造者:工人继承Builder类
 */
public class Worker extends Builder {
    private Product product;
​
    public Worker() {
        product=new Product();
    }
​
    @Override
    void buildA() {
        product.setBuildA("A");
        System.out.println("A");
​
    }
​
    @Override
    void buildB() {
        product.setBuildB("B");
        System.out.println("B");
    }
​
    @Override
    Product getProduct() {
        return product;
    }
}
package com.study.shejiPattern.builder.demo;
​
/**
 * 产品
 */
public class Product {
​
​
    private String buildA;
    private String buildB;
​
    public String getBuildA() {
        return buildA;
    }
​
    public void setBuildA(String buildA) {
        this.buildA = buildA;
    }
​
    public String getBuildB() {
        return buildB;
    }
​
    public void setBuildB(String buildB) {
        this.buildB = buildB;
    }
​
    @Override
    public String toString() {
        return "Product{" +
                "buildA='" + buildA + '\'' +
                ", buildB='" + buildB + '\'' +
                '}';
    }
}
package com.study.shejiPattern.builder.demo;
​
/**
 * 指挥构建工程
 * 指挥建构者如何构建产品 调用先后次序
 */
public class Director {
     //指挥工人构建房子  对象的构建过程
    public Product build(Builder builder){
        builder.buildA();
        builder.buildB();
        return builder.getProduct();
    }
}
package com.study.shejiPattern.builder.demo;
​
public class Client {
    public static void main(String[] args) {
        //指挥
        Director director=new Director();
        //指挥具体的工人
        Product build = director.build(new Worker());
        System.out.println(build.toString());
    }
​
}

(5)原型模式

概念:创建复杂对象时,可以创建当前对象的克隆。创建重复对象。

主要就是可以被克隆的对象实现一个接口Cloneable重写clone()

主要是分为浅克隆和深克隆

浅克隆:

直接重写父类的clone()

package com.study.shejiPattern.prototype;
​
import java.util.Date;
​
/**
 * 需要被clone的对象
 */
public class Video implements Cloneable {
    private String name;
​
    private Date createTime;
​
    @Override
    protected Object clone() throws CloneNotSupportedException {
    
        return super.clone();
    }
​
    public Video(){
​
​
    }
​
    public Video(String name, Date createTime) {
        this.name = name;
        this.createTime = createTime;
    }
​
    @Override
    public String toString() {
        return "Video{" +
                "name='" + name + '\'' +
                ", createTime=" + createTime +
                '}';
    }
​
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    public Date getCreateTime() {
        return createTime;
    }
​
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
}
package com.study.shejiPattern.prototype;
​
import java.text.ParseException;
import java.util.Date;
​
public class Bilili {
​
    public static void main(String[] args) throws CloneNotSupportedException, ParseException {
        Date date=new Date();
        Video v1 = new Video("java", date);
        Video v2 = (Video) v1.clone();
        System.out.println("v1:"+v1);
        System.out.println("v2:"+v2);
//        System.out.println("v1HashCode:"+v1.hashCode());
//        System.out.println("v2HashCode:"+v2.hashCode());
​
//        System.out.println("=============");
//        SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyyMMdd");
//        v1.setCreateTime(simpleDateFormat.parse("20221023"));
        date.setTime(22222);
​
        System.out.println("v1:"+v1);
        System.out.println("v2:"+v2);
​
//        System.out.println("=============");
//        v2.setCreateTime(simpleDateFormat.parse("20221024"));
//        System.out.println("v1:"+v1);
//        System.out.println("v2:"+v2);
​
​
    }
}

改变date值之后:v1和v2一起改变

Java设计模式----创建者模式_第5张图片

Java设计模式----创建者模式_第6张图片 

 

克隆前后的对象指向同一个Date对象,所以当Date对象发生改变时,V1和v2一起改变

深克隆:

package com.study.shejiPattern.prototype;
​
import java.util.Date;
​
/***
 * 实现深克隆
 * 重写clone方法(最好的方法)
 * 不然就的利用序列化和反序列进行深克隆
 */
public class Video1 implements Cloneable {
    private String name;
​
    private Date createTime;
​
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Object obj=super.clone();
        Video1 v= (Video1) obj;
        v.createTime= (Date) this.createTime.clone();
        return obj;
    }
​
    public Video1(){
​
​
    }
​
    public Video1(String name, Date createTime) {
        this.name = name;
        this.createTime = createTime;
    }
​
    @Override
    public String toString() {
        return "Video{" +
                "name='" + name + '\'' +
                ", createTime=" + createTime +
                '}';
    }
​
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    public Date getCreateTime() {
        return createTime;
    }
​
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
}
package com.study.shejiPattern.prototype;
​
import java.util.Date;
​
public class Bilili1 {
​
    public static void main(String[] args) throws CloneNotSupportedException {
        Date date=new Date();
        Video1 v1 = new Video1("java", date);
        Video1 v2 = (Video1) v1.clone();
        System.out.println("v1:"+v1);
        System.out.println("v2:"+v2);
//        System.out.println("v1HashCode:"+v1.hashCode());
//        System.out.println("v2HashCode:"+v2.hashCode());
​
        date.setTime(22222);
​
        System.out.println("v1:"+v1);
        System.out.println("v2:"+v2);
    }
}

改变date值之后只有V1改变了,V2并没有改变

Java设计模式----创建者模式_第7张图片

Java设计模式----创建者模式_第8张图片 

 

V1和v2指向两个date,当date改变时实际上是V1指向的date发生改变,所以V1的时间发生改变,但是v2并没有改变。

 

你可能感兴趣的:(设计模式,java,单例模式,简单工厂模式,抽象工厂模式,工厂方法模式)