设计模式(GOF23)
设计模式共23种,根据功能划分为创建型,结构性,行为行三种类型模式
正确使用设计模式使程序更加标准化,提高编程思维和能力,使代码的可重用性高,可读性强,可维护性强
创建型
工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
达到创建、使用分离效果
工厂模式
定义一个用于创建对象的接口,子类想要什么对象就去调用创建该对象的接口方法
1.简单工厂
/**
* 简单工厂模式
* 违背开闭原则
*/
public class BinGanFactory {
//方法一
public static BinGan getBinGan(String s){
if ("旺旺".equals(s)){
return new WangWang();
}if("奥利奥".equals(s)){
return new AoLiAo();
}else {
return null;
}
}
// 方法二
public static BinGan getWangWang(){
return new WangWang();
}
public static BinGan getAoLiAo(){
return new AoLiAo();
}
}
//好处,代码简单干净
//坏处,无法拓展
2.工厂方法
解决简单工厂不能扩展的问题
/*工厂方法模式,将工厂抽象,自定义需要拓展的工厂类型*/
public interface BinGanFactory {
BinGan getBinGan();
}
public class QiQuFactory implements BinGanFactory {
@Override
public BinGan getBinGan() {
return new QiQu();
}
}
public class QiQu implements BinGan {
@Override
public void name() {
System.out.println("奇趣饼干");
}
}
抽象工厂模式
工厂方法:多态性工厂,如要加入新的对象,加入新的工厂类就行了,以前的不用修改
抽象工厂:和工厂方法最大区别是对多个产品族
public interface FoodFactory {
BinGan getBinGan();
XueGao getXueGao();
}
public class AoLiAoFactory implements FoodFactory {
@Override
public BinGan getBinGan() {
return new AoLiAo();
}
@Override
public XueGao getXueGao() {
return new AoLiAoXueGao();
}
}
单例模式
饿汉式
/**
* 饿汉式
*/
public class Hungry {
private int[] arr1=new int[1024*1024];
private int[] arr2=new int[1024*1024];
// 私有空参构造,防止子类调用创建
private Hungry(){};
public static Hungry getInstance(){
return new Hungry();
}
}
懒汉式
/**
* 懒汉式
*/
public class LazyMan {
private int[] arr1=new int[1024*1024];
private int[] arr2=new int[1024*1024];
//volatile避免指令重排
private volatile static LazyMan lazyMan;
// 只要是单例模式都私有构造器
private LazyMan(){};
//线程不安全
/* public static LazyMan getInstance(){
if (lazyMan==null){
return new LazyMan();
}
return lazyMan;
}*/
//使用双重检测锁模式结局线程安全
public static LazyMan getInstance(){
if (lazyMan==null){
synchronized (LazyMan.class){
if (lazyMan==null){
return new LazyMan();//不是原子操作
/*new 创建对象
* 1.分配内存空间
* 2.执行构造方法,初始化对象
* 3.把对象指向空间
* 123
* 132
* 使用了volatile,防止对象还没初始化就指向了空间
* */
}
}
}
return lazyMan;
}
}
建造者模式
封装一个复杂对象构造过程,并允许按步骤构造
/**
* 建造者模式
* 抽象建造者:方法、过程
*/
public interface Builder {
void buildA(); //地基
void buildB(); //钢筋工程
void buildC(); //电线
void buildD(); //粉刷
Product over(); //完工
}
/**
* 高楼工人
*/
public class Worker implements Builder {
private Product product;
public Worker() {
product=new Product();
}
@Override
public void buildA() {
System.out.println("工人开始打高楼地基");
product.setA("地基");
}
@Override
public void buildB() {
System.out.println("工人开始做高楼钢筋水泥");
product.setA("钢筋工程");
}
@Override
public void buildC() {
System.out.println("工人铺高楼电线");
product.setC("电线");
}
@Override
public void buildD() {
System.out.println("工人开始高楼粉刷");
product.setD("粉刷");
}
@Override
public Product over() {
return product;
}
}
//指挥,导演。 指挥建造者如何构建产品。控制调用先后顺序
public class Director {
public Product build(Builder builder){
//具体步骤顺序
builder.buildA();
builder.buildB();
builder.buildC();
builder.buildD();
return builder.over();
}
}
public class Product {
private String a;
private String b;
private String c;
private String d;
}
//--------测试--------
public static void main(String[] args) {
Director director = new Director();
Product build = director.build(new Worker());
System.out.println(build.toString());
}
-
应用场景
- 生成的产品对象有复杂的结构,且这些产品有共性
- 隔离复杂对象的创建和使用,并使的相同的创建过程可以创建不同的产品
-
建造者模式和抽象工厂模式区别
- 抽象工厂返回的使一个产品族的一系列产品。建造者模式返回的使一个组装好的完整产品
- 抽象工厂调用工厂(建造者)方法获取对象,建造者指挥
director.build(new Worker());
给我对象,不直接调用建造者的相关方法 - 如果将抽象工厂看成汽车配件生产工厂,生产一个产品族(汽车配件)的产品,那么建造者模式就是汽车组装工厂。
原型模式
需要一个原型对象,通过克隆原型对象来获取新对象
/**
* 原型模式
* 1.实现一个接口 Cloneable
* 2.重写一个方法 clone
*/
public class Video implements Cloneable{
private String name;
private Date createTime;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
//原型对象
Date date = new Date();
Video video = new Video();
video.setCreateTime(date);
System.out.println(video);
//克隆
Video clone = (Video) video.clone();
public class Video implements Cloneable{
private String name;
private Date createTime;
@Override
protected Object clone() throws CloneNotSupportedException {
//实现深克隆:改造克隆方法
Video clone = (Video) super.clone();
//将引用也克隆一份
clone.createTime= (Date) this.createTime.clone();
return clone;
}
}
结构型
适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式
适配器模式
将某个类的接口转换成客户端期望的另一个接口表示,使得原本由于接口不兼容而不能一起工作的类能一起工作。
角色:适配器,需要被适配的类,适配目标
继承方式:
public interface NetToUsb {
void handleRequest();
}
//适配器
public class Adapter extends Adaptee implements NetToUsb{
@Override
public void handleRequest() {
super.request(); //可以上网了
}
}
/**
* 要被适配的类:网线
*/
public class Adaptee {
void request(){
System.out.println("连接网线上网");
}
}
//目标
public class Computer {
void net(NetToUsb adapter){
//上网的具体实现,找一个转接头
adapter.handleRequest();
}
public static void main(String[] args) {
//继承
Computer computer = new Computer();//电脑
Adapter adapter = new Adapter();//适配器(由于继承,适配器化身网线了)
computer.net(adapter);
}
}
//弊端:单继承
组合方式:
public class Adapter2 implements NetToUsb{
private Adaptee adaptee;
public Adapter2(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void handleRequest() {
adaptee.request(); //可以上网了
}
}
public class Computer {
void net(NetToUsb adapter){
//上网的具体实现,找一个转接头
adapter.handleRequest();
}
public static void main(String[] args) {
//继承
// Computer computer = new Computer();//电脑
// Adapter adapter = new Adapter();//适配器
// computer.net(adapter);
//组合
Computer computer = new Computer();//电脑
Adaptee adaptee = new Adaptee();//网线
Adapter2 adapter2 = new Adapter2(adaptee);//适配器
computer.net(adapter2);
}
}
桥接模式
一个类存在两个独立变化的维度,且这两个维度都需要进行扩展时,使用桥接模式关联两个维度
public interface Brand {
void info();
}
public class Apple implements Brand{
@Override
public void info() {
System.out.print("苹果");
}
}
public abstract class Computer {
protected Brand brand;
public Computer(Brand brand) {
this.brand = brand;
}
public void info(){
brand.info();
}
}
class Desktop extends Computer{
public Desktop(Brand brand) {
super(brand);
}
@Override
public void info() {
super.info();
System.out.print("台式机");
}
}
public class Test {
public static void main(String[] args) {
//苹果笔记本
//桥接了品牌和产品信息
Apple apple = new Apple();
Computer desktop = new Desktop(apple);
desktop.info();
}
}