常用的设计模式
一 创建型模式
1-单例模式
1.Example
// 饿汉
public class SingletonExample {
private static boolean flag = false;
private static final SingletonExample singletonExample = new SingletonExample();
private SingletonExample() {
//防止反射创建,正常不需要
if (flag) {
throw new RuntimeException();
} else {
flag = true;
}
}
public static SingletonExample getInstance() {
return singletonExample;
}
}
// 懒汉
public class SingletonPattern1 {
private static boolean flag = false;
private SingletonPattern1() {
if (flag) {
throw new RuntimeException();
} else {
flag = true;
}
}
private static volatile SingletonPattern1 singletonPattern1 = null;
/**
* 懒汉模式非线程安全,需要加上线程安全
*
* @return
*/
public static SingletonPattern1 getInstance() {
if (singletonPattern1 == null) {
singletonPattern1 = new SingletonPattern1();
}
return singletonPattern1;
}
2.特点和使用场景:
1>优点
只有一个实例,减少内存开销;
2>缺点
扩展困难,只能修改代码
3.使用场景
windows的任务管理器 ,windows的回收站 ,同步计数器
2-工厂模式
1.Example
基类
//子类1
public class Cat implements Animal {
@Override
public void getName() {
System.out.println("cat");
}
@Override
public void playGame() {
System.out.println("猫走猫步");
}
}
//子类2
public class Dog implements Animal {
@Override
public void getName() {
System.out.println("dog");
}
@Override
public void playGame() {
System.out.println("狗嗷嗷叫");
}
}
//父接口
public interface Animal {
void getName();
void playGame();
}
//枚举类
public enum AnimalEnum {
ANIMAL_CAT("1", Cat.class, "猫"),
ANIMAL_DOG("2", Dog.class,"狗"),
;
private String code;
private Class aClass;
private String desc;
public Class getaClass() {
return aClass;
}
public String getDesc() {
return desc;
}
AnimalEnum(String code, Class aClass, String desc) {
this.code = code;
this.aClass = aClass;
this.desc = desc;
}
public String getCode() {
return code;
}
public static AnimalEnum getAnimalByCode(String code){
for(AnimalEnum animalEnum :AnimalEnum.values()){
if (animalEnum.getCode().equals(code)){
return animalEnum;
}
}
return null;
}
}
简单工厂
//通过Map存储,type获取需要使用的类
public class AnimalFactory {
public static final HashMap<String, Animal> animalHashMap = new HashMap<>();
static {
animalHashMap.put("1",new Cat());
animalHashMap.put("2",new Dog());
}
public static Animal getAnimal(String type){
return animalHashMap.get(type);
}
}
反射工厂
//通过class获取反射 通过泛型通用
public class FactoryAnimal {
public static <T> T create(Class<? extends T> clazz, Class<T> tClass) {
try {
if (clazz != null) {
return clazz.newInstance();
}
} catch (Exception e) {
throw new RuntimeException("创建基类报错");
}
return null;
}
}
测试:
public class FactoryTest {
@Test
public void get(){
String type="1";
//type 获取反射
Animal animal = AnimalFactory.getAnimal(type);
animal.getName();
Class<Cat> catClass = Cat.class;
Class<? extends Animal> aClass = animal.getClass();
if (animal==null){
throw new RuntimeException();
}
//通过枚举反射获取
Animal animal1 = FactoryAnimal.create(AnimalEnum.getAnimalByCode(type).getaClass(),Animal.class);
animal.getName();
}
}
/*结果:cat
cat
Process finished with exit code 0
*/
2.特点和使用场景:
1>优点
避免创建类的重复代码出现,同时避免同一类的各种产品,同一种规则的不同实现;
2>缺点
多一种产品就需要多一种实现的方式,需要通过代码解决
3>使用场景
不同产品大部分流程相同,特定流程特定处理的问题;
例如:订单不同产品,不同发货的问题(虚拟发货,实体发货)
3.原型模式
1.Example
基类
@AllArgsConstructor
@NoArgsConstructor
public class Book implements Cloneable,Serializable{
private int price;
private String color;
//简单克隆基础类,地址指向一致
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
//深克隆,地址指向不一致
protected Object deepClone() throws IOException, ClassNotFoundException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
测试类:
public class BookTest {
public static void main(String[] args) throws Exception {
Book book = new Book();
book.setColor("123");
book.setPrice(123);
//浅克隆
long time1 = new Date().getTime();
//循环百万次
for (int i = 0; i <1000000; i++) {
Object clone = book.clone();
}
long time2 = new Date().getTime();
System.out.println("浅克隆事件 = " + (time2-time1));
//深克隆
long time3 = new Date().getTime();
//循环百万次
for (int i = 0; i <1000000 ; i++) {
Object o = book.deepClone();
}
long time4 = new Date().getTime();
System.out.println("深克隆 = " + (time4-time3));
//对象复制 地址指向不同,同时赋值
long time5 = new Date().getTime();
//循环百万次
for (int i = 0; i <1000000 ; i++) {
Book book1 = new Book();
book1.setColor(book.getColor());
book1.setPrice(book.getPrice());
}
long time6 = new Date().getTime();
System.out.println("对象set = " + (time6-time5));
//对象复制 地址指向不同,同时赋值
long time7 = new Date().getTime();
//循环百万次
for (int i = 0; i <1000000 ; i++) {
Book book1 = new Book();
BeanUtils.copyProperties(book,book1);
}
long time8 = new Date().getTime();
System.out.println("beanUtil = " + (time8-time7));
}
}
2.特点和使用场景:
1>优点
网上表示能够比new 更节约时间,简化创建过程
2>缺点
没啥有点
3>使用场景
没想到特别好的场景,set速度更快,懒人用BeanUtils可能更好
4.建造者模式
1.建造者模式平常用的比较比较多的就是builder.链式创建对象;目前用封装的比较多
二 结构模式
1-代理模式
1-静态代理**
2-动态代理
1.Example
基类
public interface People {
void sleep();
}
public class Boy implements People {
@Override
public void sleep() {
System.out.println("boy");
}
}
public class Girl implements People{
@Override
public void sleep() {
System.out.println("girl");
}
}
动态代理
public class proxyAction<T> implements InvocationHandler {
private T obj;
public proxyAction() {
}
public T getObject(T obj) {
this.obj = obj;
Class aClass = obj.getClass();
T o = (T)Proxy.newProxyInstance(aClass.getClassLoader(), aClass.getInterfaces(), this);
return o;
}
@Override
public Object invoke(Object o, Method method, Object[] args) throws Throwable {
System.out.println(1);
Object invoke = method.invoke(this.obj, args);
System.out.println(2);
return invoke;
}
//测试
public static void main(String[] args) {
Girl girl = new Girl();
//创建代理是确定泛型
proxyAction<People> proxyAction = new proxyAction();
People people = proxyAction.getObject(girl);
people.sleep();
}
/*
//测试结果
1
girl
2
*/
}
2-适配者模式
1.Example
public interface Tyre {
int getTyreOne();
int getTyreTwo();
int getTyreThree();
int getTyreFour();
}
public interface Vehicle {
int getTyre();
}
public class Bicycle implements Vehicle{
@Override
public int getTyre() {
TyreLoad tyreLoad = new TyreLoad();
return tyreLoad.getTyre(1);
}
}
public class Car implements Vehicle{
@Override
public int getTyre() {
TyreLoad tyreLoad = new TyreLoad();
return tyreLoad.getTyre(4);
}
}
// 适配器
public class TyreLoad implements Tyre{
@Override
public int getTyreOne() {
return 1;
}
@Override
public int getTyreTwo() {
return 2;
}
@Override
public int getTyreThree() {
return 3;
}
@Override
public int getTyreFour() {
return 4;
}
public int getTyre(int a){
if (a==1){
return getTyreOne();
}
if (a==2){
return getTyreTwo();
}
if (a==3){
return getTyreThree();
}
if (a==4){
return getTyreFour();
}
return 0;
}
// 测试类
public class AdapterTest {
public static void main(String[] args) {
Car car = new Car();
System.out.println(car.getTyre());
}
}
/* 输出
4
*/
优点:
根据不同的类型给到不同的解决方案;
只定义规则,不涉及具体实现;
使用场景:
jdbc 连接数据库等
3-装饰模式
1.example
//房子
@Data
public class Home {
//房价
private int price;
//房子
private String desc;
//实体构造
public Home(Home home) {
this.desc = home.getDesc();
this.price = home.getPrice();
}
public Home(int price, String desc) {
this.price = price;
this.desc = desc;
}
}
//装饰类
public class Door extends Home{
//房价
private int price;
//房子
private String desc;
public Door(Home home) {
super(home);
}
@Override
public int getPrice() {
return super.getPrice()+2;
}
@Override
public String getDesc() {
return "有门的"+super.getDesc();
}
}
//测试类
public class DecoratorTest {
public static void main(String[] args) {
//构造基础类房子
Home home = new Home(123, "房子");
example(home);
//装饰房子
Door door = new Door(home);
example(door);
}
public static void example(Home home){
System.out.println(home.getDesc()+"价格是"+home.getPrice()+"万元");
}
}
/*
运行结果
房子价格是123万元
有门的房子价格是125万元
*/
优点:
装饰模式很明显就是装修,对于原有功能的基础上添加功能,相比较静态代理而言更直接;
场景:
场景比较多,多数为对于同一产品的不同的处理,比如商品的包装;
4-桥接模式
1.example
不做具体代码实现,只是一种方式
桥接模式相比较适配差不多;
比如手机需要充电,都是充电头加充电线,以及连接方式,桥接如果没有现成结果可以制造一个方式;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tZVKfOgK-1683525491046)(C:\Users\33478\AppData\Roaming\Typora\typora-user-images\image-20230407103038727.png)]
不管中间的实现,只关注头跟尾;