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();   //22hungrySingle2.showName();   //22if(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 {@Overridepublic Car getCar() {return new CarImpl1();}
}
public class Consumer {public static void main(String[] args) {Car car1=new Car1Factory().getCar();}
}

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

(3)抽象工产模式

概念:

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

产品族:

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

代码实现:

产品:

phone:

/**8* 手机产品接口*/
public interface IphoneProduct {
​void start();void shut();void callup();void send();
}
package com.study.shejiPattern.factory.abstract1;
//小米手机
public class XiaomiPhone implements IphoneProduct {@Overridepublic void start() {System.out.println("开启小米手机");}
​@Overridepublic void shut() {System.out.println("小米手机");}
​@Overridepublic void callup() {System.out.println("小米手机");}
​@Overridepublic void send() {System.out.println("小米手机");}
}package com.study.shejiPattern.factory.abstract1;
​
public class HuaWeiPhone implements IphoneProduct {@Overridepublic void start() {System.out.println("huawei");}
​@Overridepublic void shut() {System.out.println("huawei");}
​@Overridepublic void callup() {System.out.println("huawei");}
​@Overridepublic 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 {@Overridepublic IphoneProduct iphoneProduct() {return new HuaWeiPhone();}
​@Overridepublic IRouterProduct routeProduct() {return new HuweiRouter();}
}
package com.study.shejiPattern.factory.abstract1;
​
/*** 小米生产*/
public class XiaomiFactory implements IProductFactory {@Overridepublic IphoneProduct iphoneProduct() {return new XiaomiPhone();}
​@Overridepublic 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();}
}

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

扩充产品族:难

扩充产品等级:简单

(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();}
​@Overridevoid buildA() {product.setBuildA("A");System.out.println("A");
​}
​@Overridevoid buildB() {product.setBuildB("B");System.out.println("B");}
​@OverrideProduct 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;}
​@Overridepublic 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;
​@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
​public Video(){
​
​}
​public Video(String name, Date createTime) {this.name = name;this.createTime = createTime;}
​@Overridepublic 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一起改变

克隆前后的对象指向同一个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;
​@Overrideprotected 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;}
​@Overridepublic 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并没有改变

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

Java设计模式----创建者模式相关推荐

  1. 重学Java设计模式-创建者模式-工厂方法模式

    重学Java设计模式-创建者模式-工厂方法模式 内容摘自:重学 Java 设计模式:实战工厂方法模式「多种类型商品不同接口,统一发奖服务搭建场景」 | bugstack 虫洞栈 工厂方法模式介绍 图片 ...

  2. 重学Java设计模式-创建者模式-建造者模式

    重学Java设计模式-创建者模式-建造者模式 内容摘自:重学 Java 设计模式:实战建造者模式「各项装修物料组合套餐选配场景」 | bugstack 虫洞栈 建造者模式介绍 图片来自:https:/ ...

  3. Java设计模式——创建者模式之工厂模式

    文章目录 2 工厂模式*** 2.1 概述 2.2 简单工厂模式*** 2.2.1 结构 2.2.2 实现 2.2.4 优缺点 2.2.3 扩展 2.3 工厂方法模式*** 2.3.1 概念 2.3. ...

  4. 设计模式-创建者模式篇

    设计模式 目录: 一.单例模式 二.工厂模式 三.抽象工厂模式 四.原型模式 五.建造者模式 注:学习视频:黑马程序员Java设计模式 创建者模式 创建型模式的主要关注点是"怎样创建对象?& ...

  5. Java设计模式——Builder模式

    前言 之前写Android程序的时候,经常会用到Dialog(对话框)这个控件.我们在使用Dialog,比如AlertDialog的时候就用到了这里要说明的Builder模式.现在我们来看一下这样的一 ...

  6. Java 设计模式——状态模式

    概述 很多人在说状态模式的时候总拿策略模式来进行对比,可能他们的类图会有一点类似,可我却不认为他们有多么相像.你可以阅读<Java设计模式--策略模式>这篇博客,并与本文对比,以找到蛛丝马 ...

  7. Java设计模式-工厂模式(3)抽象工厂模式

    在Java设计模式-工厂模式(2)工厂方法模式 我们知道了工厂方法模式解决了简单工厂模式中的缺陷,做到了满足开闭原则,但是时代是进步的,进而又产生新的问题,工厂难道只能生产一种东西吗.我们所见到的工厂 ...

  8. Java设计模式-工厂模式(2)工厂方法模式

    在Java设计模式-工厂模式(1)简单工厂模式 中我们介绍了简单工厂模式,提到了简单工厂模式违背了开闭原则,而"工厂方法模式"是对简单工厂模式的进一步抽象化,其好处是可以使系统在不 ...

  9. Java设计模式-工厂模式(1)简单工厂模式

    Java设计模式-工厂模式(1)简单工厂模式 一.前言 1)例子 2)类图关系 3)代码实现 二.简单工厂模式 2.1.概述: 2.2.类图关系: 2.3.代码修改: 2.4.优缺点 2.5.扩展-简 ...

最新文章

  1. 报错内容 IndentationError: unindent does not match any outer indentation level
  2. 计算机组成原理 — CPU — 指令集架构类型
  3. SQL Server on Ubuntu——Ubuntu上的SQL Server(全截图)
  4. 『软件工程12』软件工程实践方法——软件测试
  5. mysql空洞数据,Mysql 表空间和 数据页空洞
  6. 实战SQL Server 2005镜像配置全过程
  7. 【转】ABP源码分析三十九:ABP.Hangfire
  8. 最近几年出现的新技术
  9. express url跳转(重定向)的实现:res.location() res.redirect()
  10. (转)浅说深度学习:核心概念
  11. 老毛子最想固件,支持打印机了
  12. 荐一个不错的UI设计网站: uimaker
  13. SQL Server2012企业版与标准版比较
  14. 不要迷恋我,虽然我利用Python来耍植物大战僵尸
  15. (十)Intellij 远程调试 a bug
  16. java方法重写[详解]
  17. Ubuntu16.04编译android6.0.1源码记录
  18. boss直聘账号异常登不上_五条人XBOSS直聘推出麻将盲盒
  19. win10 nginx部署静态资源服务器和HTML
  20. 中国电信天翼开放平台应用内计费SDK助力IP产业升级

热门文章

  1. L2-039 清点代码库
  2. 用 Python 对 Excel 表格内数据进行去重、分类,标记异常及分析
  3. 用python处理excel的基本语法_Python操作Excel学习笔记(28):条件格式
  4. 如何提升程序员的非技术才能
  5. android调用系统相机返回图片模糊
  6. git官网 中文教程 使用手册 说明书
  7. 海洋CMS忘记后台管理员密码解决方法
  8. 计算机毕业设计springboot+uniapp点餐外卖系统源码
  9. 进入邻居家的无线路由器
  10. 【PAT】B1032 挖掘机技术哪家强 (20 分)_C语言实现