JAVA 中的设计模式(一)
1.1、创建型模式(5种)
1.1.1、单列模式:在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在。这样的模式有几个好处:
1、某些类创建比较频繁,对于一些大型的对象,这是一笔很大的系统开销。
2、省去了new操作符,降低了系统内存的使用频率,减轻GC压力。
3、有些类如交易所的核心交易引擎,控制着交易流程,如果该类可以创建多个的话,系统完全乱了。(比如一个军队出现了多个司令员同时指挥,肯定会乱成一团),所以只有使用单例模式,才能保证核心交易服务器独立控制整个流程。
适用场景: 1.需要生成唯一序列的环境
2.需要频繁实例化然后销毁的对象。
3.创建对象时耗时过多或者耗资源过多,但又经常用到的对象。
4.方便资源相互通信的环境
优点:1.实现了对唯一实例访问的可控
2.对于一些需要频繁创建和销毁的对象来说可以提高系统的性能。
缺点:1. 不适用于变化频繁的对象
2.滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出。
3.如果实例化的对象长时间不被利用,系统会认为该对象是垃圾而被回收,这可能会导致对象状态的丢失。
代码示例如下图
package com.pattern.Singleton;
/**
- 单例模式
/
public class Singleton {
/ 持有私有静态实例,防止被引用,此处赋值为null,目的是实现延迟加载 /
private static Singleton singleton = null;
/ 私有构造方法,防止被实例化 /
private Singleton(){
}
/ 静态工程方法,创建实例,在多线程的情况下可能会出现问题,所以加上同步锁synchronized /
public synchronized static Singleton getSingleton(){
if (singleton != null){
return singleton;
}else{
return new Singleton();
}
}
/ 如果该对象被用于序列化,可以保证对象在序列化前后保持一致 /
public Object resolve(){
return singleton;
}
}
1.1.2 、原型模式:通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象。
这种形式涉及到三个角色:
(1)客户(Client)角色:客户类提出创建对象的请求。
(2)抽象原型(Prototype)角色:这是一个抽象角色,通常由一个Java接口或Java抽象类实现。此角色给出所有的具体原型类所需的接口。
(3)具体原型(Concrete Prototype)角色:被复制的对象。此角色需要实现抽象的原型角色所要求的接口。
个人理解:原型模式就是多态的具体实现,通过用方法重写的方式来实现父引用指向子实例
代码示例如下
package com.pattern.Prototype;
/* - 抽象原型角色
/
public interface Prototype {
/*- 克隆自身的方法
- @return 一个从自身克隆出来的对象
*/
public Object clone();
}
package com.pattern.Prototype;
/**
- 具体原型角色
*/
public class ConcretePrototype1 implements Prototype {
@Override
public Object clone() {
//最简单的克隆,新建一个自身对象,由于没有属性就不再复制值了
Prototype prototype = new ConcretePrototype1();
return prototype;
}
}
package com.pattern.Prototype;
/**
- 具体原型角色
*/
public class ConcretePrototype2 implements Prototype {
@Override
public Object clone() {
//最简单的克隆,新建一个自身对象,由于没有属性就不再复制值了
Prototype prototype = new ConcretePrototype2();
return prototype;
}
}
package com.pattern.Prototype;
public class Client {
/**
*** 持有需要使用的原型接口对象
/
private Prototype prototype;
/***
* 构造方法,传入需要使用的原型接口对象
*/
public Client(Prototype prototype){
this.prototype = prototype;
}
public void operation(Prototype prototype){
//需要创建原型接口的对象
Prototype copyprototype = (Prototype)prototype.clone();
}
}
1.1.3、工厂模式:分为三种工厂模式,简单工厂模式,工厂模式,抽象工厂模式。
1、简单工厂模式:专门定义一个类来 负责创建其他类的实例,被创建的实例通常都具有相同的父类,具有类似的行为特征,代码示例如下
//鼠标基类
class Mouse{
public void sayHi(){};
}
//鼠标扩展类
class DellMouse extends Mouse{
@Override
public void sayHi() {
System.out.println("产品:戴尔鼠标");
}
}
class HpMouse extends Mouse{
@Override
public void sayHi() {
System.out.println("产品:惠普鼠标");
}
}
//鼠标工厂
class MouseFactory{
//生产鼠标的方法,所有的鼠标都通过该方法生成
public static Mouse createMouse(int i) {
switch (i) {
case 0: return new DellMouse();
case 1: return new HpMouse();
default: return null;
}
}
}
class NormFactory {
public static void main(String[] args) {
Mouse hpm = MouseFactory.createMouse(1);
Mouse dellm = MouseFactory.createMouse(0);
hpm.sayHi();
dellm.sayHi();
}
}
2、工厂模式:定义一个创建对象的接口,让子类来决定实例化那个类,使一个的类的实例化延迟到子类。
个人理解:创建一个工厂的总接口,在通过不同的对象工厂去实现这个总工厂,在对应的对象工厂中覆盖总共工厂的方法,来返回对应工厂对应对象的实例。好处方便代码解耦,需要什么对象工厂直接实现总接口工厂就可以了。
3、抽象工厂模式:提供一个创建一系列相关或相互依赖对象接口,而无需指定他们具体的类。代码如下所示
class Mouse{
public void sayHi(){};
}
class DellMouse extends Mouse {
@Override
public void sayHi() {
System.out.println("产品:戴尔鼠标");
}
}
class HpMouse extends Mouse {
@Override
public void sayHi() {
System.out.println("产品:惠普鼠标");
}
}
class KeyBoard {
public void kick(){};
}
class HpKeyBoard extends KeyBoard {
@Override
public void kick() {
System.out.println("产品:惠普键盘");
}
}
class DellKeyBoard extends KeyBoard {
@Override
public void kick() {
System.out.println("产品:戴尔键盘");
}
}
//总的工厂接口
interface PcFactory {
public Mouse createMouse() ;
public KeyBoard createKeyBoard() ;
}
class HpFactory implements PcFactory {
@Override
public Mouse createMouse() {
return new HpMouse();
}
@Override
public KeyBoard createKeyBoard() {
return new HpKeyBoard();
}
}
class DellFactory implements PcFactory {
@Override
public Mouse createMouse() {
return new DellMouse();
}
@Override
public KeyBoard createKeyBoard() {
return new DellKeyBoard();
}
}
//当需要增加一个华硕工厂时:
class AsusMouse extends Mouse {
@Override
public void sayHi() {
System.out.println("产品:华硕鼠标");
}
}
class AsusKeyBoard extends KeyBoard {
@Override
public void kick() {
System.out.println("产品:华硕键盘");
}
}
class AsusFactory implements PcFactory {
@Override
public Mouse createMouse() {
return new AsusMouse();
}
@Override
public KeyBoard createKeyBoard() {
return new AsusKeyBoard();
}
}
public class NormFactory {
public static void main(String[] args) {
PcFactory hpFact = new HpFactory();
Mouse hpm = hpFact.createMouse();
KeyBoard hpkbd = hpFact.createKeyBoard();
PcFactory dellFact = new DellFactory();
Mouse dellm = dellFact.createMouse();
KeyBoard dellkbd = dellFact.createKeyBoard();
hpm.sayHi();
dellm.sayHi();
hpkbd.kick();
dellkbd.kick();
}
}
1.1.4、建造者模式:是将一个复杂的对象的构建与它的表示分离,使
得同样的构建过程可以创建不同的表示。创建者模式隐藏了复杂对象的创建过程,它把复杂对象的创建过程加以抽象,通过子类继承或者重载的方式,动态的创建具有复合属性的对象。
个人理解:建造者模式不需要在构造器中传对应的参数,而是你要什么参数可以直接set进去。
package com.pattern.Builder;
// 省略 getter 和 setter 方法
class Computer {
private String cpu;
private String screen;
private String memory;
private String mainboard;
public Computer(String cpu, String screen, String memory, String mainboard) {
this.cpu = cpu;
this.screen = screen;
this.memory = memory;
this.mainboard = mainboard;
}
}
class NewComputer {
private String cpu;
private String screen;
private String memory;
private String mainboard;
public NewComputer() {
throw new RuntimeException();
}
private NewComputer(Builder builder) {
cpu = builder.cpu;
screen = builder.screen;
memory = builder.memory;
mainboard = builder.mainboard;
}
public static final class Builder {
private String cpu;
private String screen;
private String memory;
private String mainboard;
public Builder() {}
public Builder cpu(String val) {
cpu = val;
return this;
}
public Builder screen(String val) {
screen = val;
return this;
}
public Builder memory(String val) {
memory = val;
return this;
}
public Builder mainboard(String val) {
mainboard = val;
return this;
}
public NewComputer build() {
return new NewComputer(this);}
}
}
class Click {
public static void main(String[] args) {
// 非 Builder 模式
Computer computer = new Computer("cpu", "screen", "memory", "mainboard");
// Builder 模式
NewComputer newComputer = new NewComputer.Builder()
.cpu("cpu")
.screen("screen")
.memory("memory")
.mainboard("mainboard")
.build();
}
}
上面的示例代码只是传入四个参数,如果参数是十四个甚至更多,builder 模式的优势将会更加明显,传递参数更加灵活,代码具有更高的可读性。
1.1.5、原始模式:原始模型模式属于对象的创建模式。通过一个原型对象来指明要创建对象的类型,然后用复制原型对象的方法来创建出更多同类型的对象,主要就是用到了clone()这个方法进行克隆。