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(); //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设计模式----创建者模式相关推荐
- 重学Java设计模式-创建者模式-工厂方法模式
重学Java设计模式-创建者模式-工厂方法模式 内容摘自:重学 Java 设计模式:实战工厂方法模式「多种类型商品不同接口,统一发奖服务搭建场景」 | bugstack 虫洞栈 工厂方法模式介绍 图片 ...
- 重学Java设计模式-创建者模式-建造者模式
重学Java设计模式-创建者模式-建造者模式 内容摘自:重学 Java 设计模式:实战建造者模式「各项装修物料组合套餐选配场景」 | bugstack 虫洞栈 建造者模式介绍 图片来自:https:/ ...
- 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. ...
- 设计模式-创建者模式篇
设计模式 目录: 一.单例模式 二.工厂模式 三.抽象工厂模式 四.原型模式 五.建造者模式 注:学习视频:黑马程序员Java设计模式 创建者模式 创建型模式的主要关注点是"怎样创建对象?& ...
- Java设计模式——Builder模式
前言 之前写Android程序的时候,经常会用到Dialog(对话框)这个控件.我们在使用Dialog,比如AlertDialog的时候就用到了这里要说明的Builder模式.现在我们来看一下这样的一 ...
- Java 设计模式——状态模式
概述 很多人在说状态模式的时候总拿策略模式来进行对比,可能他们的类图会有一点类似,可我却不认为他们有多么相像.你可以阅读<Java设计模式--策略模式>这篇博客,并与本文对比,以找到蛛丝马 ...
- Java设计模式-工厂模式(3)抽象工厂模式
在Java设计模式-工厂模式(2)工厂方法模式 我们知道了工厂方法模式解决了简单工厂模式中的缺陷,做到了满足开闭原则,但是时代是进步的,进而又产生新的问题,工厂难道只能生产一种东西吗.我们所见到的工厂 ...
- Java设计模式-工厂模式(2)工厂方法模式
在Java设计模式-工厂模式(1)简单工厂模式 中我们介绍了简单工厂模式,提到了简单工厂模式违背了开闭原则,而"工厂方法模式"是对简单工厂模式的进一步抽象化,其好处是可以使系统在不 ...
- Java设计模式-工厂模式(1)简单工厂模式
Java设计模式-工厂模式(1)简单工厂模式 一.前言 1)例子 2)类图关系 3)代码实现 二.简单工厂模式 2.1.概述: 2.2.类图关系: 2.3.代码修改: 2.4.优缺点 2.5.扩展-简 ...
最新文章
- 报错内容 IndentationError: unindent does not match any outer indentation level
- 计算机组成原理 — CPU — 指令集架构类型
- SQL Server on Ubuntu——Ubuntu上的SQL Server(全截图)
- 『软件工程12』软件工程实践方法——软件测试
- mysql空洞数据,Mysql 表空间和 数据页空洞
- 实战SQL Server 2005镜像配置全过程
- 【转】ABP源码分析三十九:ABP.Hangfire
- 最近几年出现的新技术
- express url跳转(重定向)的实现:res.location() res.redirect()
- (转)浅说深度学习:核心概念
- 老毛子最想固件,支持打印机了
- 荐一个不错的UI设计网站: uimaker
- SQL Server2012企业版与标准版比较
- 不要迷恋我,虽然我利用Python来耍植物大战僵尸
- (十)Intellij 远程调试 a bug
- java方法重写[详解]
- Ubuntu16.04编译android6.0.1源码记录
- boss直聘账号异常登不上_五条人XBOSS直聘推出麻将盲盒
- win10 nginx部署静态资源服务器和HTML
- 中国电信天翼开放平台应用内计费SDK助力IP产业升级