2.设计模式之前5种设计模式单例工厂原型建造者适配器

news2024/12/28 19:44:00

1.怎么掌握设计模式? 独孤5剑 先是锋利的剑 后面是无剑才是最强的
,GOF四人组写的<设计模式>书,包含了23种,实际可能还有其他,不要被束缚(只是覆盖了大部分).设计模式适合的人群:

1.不知道设计模式
2.有编程经验,但是写的好多代码有设计模式却不知道
3.学习过设计模式,发现有些模式好用
4.需要阅读别人的源码和框架,和设计模式
5.以前没有意识的使用设计模式,学习完恍然大悟

2.设计模式类型(4种类型,23种)

  1. 创建型模式(类的创建) 单例模式(怎么只创建1个类*) 抽象工厂模式 原型模式 建造者模式,工厂模式(*)
  2. 结构型模式(系统性问题,整个系统代码量达到大量的级别) 适配器模式,桥接模式,访问者模式 迭代器模式,观察者模式,中介者模式,忘备录模式
    解释器模式(interpreter),策略模式,装饰模式(解决类多到爆炸*)
  3. 行为型模式(方法的角度) 模板方法模式 职责链(责任链,方法的调用顺序)

3.单例模式(8种方法) 保证系统中 某个类只能存在一个对象实例,类只提供一个得到对象的方法(静态方法)

1.饿汉式singleton(立即创建对象) 优点:避免多线程同步问题(常用于单线程),写法简单 缺点: 不确定什么时候被其他类加载,造成不必要的内存浪费,不能lazy loading的效果

class Singleton{ //线程安全
               //1.私有的构造器
  private  Singleton(){}
               //2.类内部直接创建对象实例
              private final static Singleton instance=new Singleton();
               //3.暴露一个静态方法返回对象
                  public static Singleton getInstance(){
                          return instance;
                 }

        }

2.饿汉式 (创建放在)静态代码块 优缺点和1一样

  private final static Singleton instance;
	static{
	 	instance=new Singleton();
    }

3.懒汉式1(线程不安全)(静态方法调用时才创建对象) 优点:可以起到懒加载效果 缺点: 多线程会出现线程同步问题 (if判断的时候其他线程也同时判断)开发时不要使用它

   public static Singleton getInstance(){
                 if(instance == null){
                           instance=new Singleton();
                  }
                  return instance;
   }

4.懒汉式2(线程安全) 方法上加synchronized 优点: 解决线程安全问题 缺点: 效率太低(new了实例后,后面得到实例都需要经过同步方法) 开发不推荐使用

    public static synchronized Singleton getInstance(){
                 if(instance == null){
                           instance=new Singleton();
                  }
                  return instance;
   }

5.这种懒汉式 不能解决线程安全问题 开发不能用

 public static Singleton getInstance(){
                 if(instance == null){
                       synchronized(Singleton.class){ //一个线程执行完,另外同一时间执行的一个线程也会等待执行里面的语句
              instance=new Singleton();
                       }      
                  }
                  return instance;
   }

6.双重检查(使用volatile关键字和双重检查对象是否被创建) 推荐使用 优点: 解决效率(懒加载)和同步的问题

  private final static volatile Singleton instance=new Singleton();   //可以要加volatile 不是因为线程同步的问题,而是指令重排导致instance被提前赋值的问题
  public static Singleton getInstance(){
                 if(instance == null){
                       synchronized(Singleton.class){ 
                          if(instance == null){        //为什么要多判断一次呢?,由于5他可能有线程同步问题
                                                                // 这里的instance已经写了volatile(可见性,不能保证原子性.防止指令重排序)但是不能保证线程同步
                 instance=new Singleton(); 
                          }
                       }      
                  }
                  return instance;
   } 
  1. 静态内部类(有静态内部类变量new,返回对象是static静态内部类也是static) 优点保证了线程安全
    1.加载外部类的时候不会加载内部类
    2.(jvm 静态内部类只装载一次)和懒加载 推荐的
class Singleton{ 
            
  private  Singleton(){}
              
           
        
                  public static Singleton getInstance(){
                          return SingletonStatic.instance.;
                 }
               private static  class SingletonStatic{
	private final static Singleton instance=new Singleton();
              }

8.枚举(内置的成员可以创建对象) jdk1.5添加枚举实现单例模式 优点:线程安全,复制反序列化重新创建对象(effective java的josh bloch) 推荐使用

enum ENUMSINGLE8{
    INSTANCE,INSTANCE1;;

    public void play(){
        System.out.println("快和妲己一起玩耍");
    }


}
class hh{
    public static void main(String[] args) {

        //简单验证线程不安全
        CopyOnWriteArrayList list = new CopyOnWriteArrayList();
        for (int i = 1; i <=2000; i++) {
            new Thread(()->{
                ENUMSINGLE8 instance = ENUMSINGLE8.INSTANCE1;
                instance.play();
                list.add(instance.hashCode());
            }).start();
        }
        while (Thread.activeCount()>2){
            Thread.yield();
        }
        System.out.println(list);
    }
}       

3.jdk里的单例模式

1.RunTime类 饿汉式
2.使用场景 ,用于对象需要频繁(重量级对象)(耗时高)创建和销毁,检查使用的对象 工具类对象,频繁访问数据库或文件的对象(数据源或session工厂)

4.简单(静态)工厂模式(在工厂模式用得最多的,再加个静态方法setFactory)

  1. 传统方式 pizza制作过程和消费 写个Pizza类和抽象类,继承了抽象类,需要修改Pizza类 创建哪种pizza种类、
    //改进后 图11简单工厂的传统方式实现
    请添加图片描述
  1. 概念
    1.是由一个过程对象创建出哪一种产品类的实例
    2.封装实例化哪个对象的行为
    3.大量创建某种类或某批对象时使用(批量生产对象)
    图12简单工厂之改进方式实现

-----完整代码(自己不看代码,按思路敲出来,再对比别人的代码,受益匪浅…)—

    //先创建Piza抽象类
 public abstract class Pizza {
    private String name;//披萨的名字
    //披萨的操作
    //准备披萨的材料不同,我们在设计的时候要考虑多种情况
    // in fact,we have to define operation to all func(ensuring the function can not be alter)
    public abstract void prepare();
    public void cut(){
        System.out.println("cut");
    }
    public void bake(){
        System.out.println("bake");
    }
    //打包
    public void pack(){
        System.out.println("pack");
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}
  //创建他的子类
public class ChinesePiza extends Pizza{
    @Override
    public void prepare() {
        System.out.println(super.getName()+"chinese piza prepare");
    }
}
  //创建他的另外一个子类
public class PepperPiza extends Pizza{
    @Override
    public void prepare() {
        System.out.println("pepper piza prepare");
    }
}

//(核心步骤)创建简单工厂类,专门创建对象,不要加入其他功能

public class PizaSimpleFactory {
    static Pizza pizza=null;
    public static Pizza createPiza(String type){
            if(type.equals("chinese")){
                pizza = new ChinesePiza();
                pizza.setName("中国披萨");
                return pizza;
            }else if(type.equals("pepper")){
                pizza = new PepperPiza();
                pizza.setName("中国披萨");
                return pizza;
           }

            return pizza;
    }
}

//下单才调用处理业务,相当于 三层架构的 service,调用工厂创建对象

public class OrderPiza {

    void doOrder(String type){

        Pizza piza = PizaSimpleFactory.createPiza(type);
        if (piza!=null){
            piza.prepare();
            piza.bake();
            piza.cut();
            piza.pack();
        }else {
            System.out.println("创建披萨订单失败");
        }



    }

}

//相当于controller,调用创建订单

public class PizaController {
    public static void main(String[] args) {
        OrderPiza orderPiza = new OrderPiza();
        orderPiza.doOrder("pepper");
    }
}

5.工厂方法模式(对简单工厂创建类保存抽象类,到子类实现具体的功能)(现在有了具体的披萨如北京胡椒披萨)
//就是大工厂创建 对象 后小工厂创建 更小的更具体的对象
图 13工厂方法模式
//BJcheessPizza事实上是一个工厂子类请添加图片描述 //核心代码,是工厂类和子工厂 //工厂类

  public  class AllKindOfPizzaFactory {
    public  Pizza createPizza(String type) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("输入你要的具体披萨类型");
        String typeDetail = scanner.next();

        if (type.equals("bj")) {
            BJOrderPiza bjOrderPiza = new BJOrderPiza();
            return bjOrderPiza.createPizza(typeDetail);
        } else if (type.equals("ld")) {
            LDOrderPiza ldOrderPiza = new LDOrderPiza();
            return ldOrderPiza.createPizza(typeDetail);
        }
        return null;
    }


}
  //子工厂1继承大工厂
public class BJOrderPiza extends AllKindOfPizzaFactory {
    Pizza pizza;
    //违反了ocp原则
    public Pizza createPizza(String type){

        if(type.equals("chinese")){
            pizza = new BJChinesePiza();
            pizza.setName("北京中国披萨");
            return pizza;
        }else if(type.equals("pepper")){
            pizza = new BJPepperPiza();
            pizza.setName("北京胡椒披萨");
            return pizza;
        }


        return pizza;
    }


}
 //子工厂2继承大工厂
public class LDOrderPiza extends AllKindOfPizzaFactory {
    Pizza pizza;
    //违反了ocp原则
    public Pizza createPizza(String type){

        if(type.equals("chinese")){
            pizza = new LDChinesePiza();
            pizza.setName("伦敦中国披萨");
            return pizza;
        }else if(type.equals("ld")){
            pizza = new LDPepperPiza();
            pizza.setName("伦敦胡椒披萨");
            return pizza;
        }


        return pizza;
    }
}
//抽象实体类
public abstract class Pizza {
    private String name;//披萨的名字
    //披萨的操作
    //准备披萨的材料不同,我们在设计的时候要考虑多种情况
    // in fact,we have to define operation to all func(ensuring the function can not be alter)
    public abstract void prepare();
    public void cut(){
        System.out.println("cut");
    }
    public void bake(){
        System.out.println("bake");
    }
    //打包
    public void pack(){
        System.out.println("pack");
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}
//抽象实体类的子类1
public class LDPepperPiza extends Pizza {
    @Override
    public void prepare() {
        System.out.println("ldpepper piza prepare");
    }
}
//抽象实体类的子类2
public class BJPepperPiza extends Pizza {
    @Override
    public void prepare() {
        System.out.println("ldpepper piza prepare");
    }
}

public class OrderPizza {
    void doPizaOrder(String type){
        AllKindOfPizzaFactory orderPizzaFactory = new AllKindOfPizzaFactory();
        Pizza pizza = orderPizzaFactory.createPizza(type);
        if(pizza!=null){
            pizza.prepare();
            pizza.cut();
            pizza.bake();
            pizza.pack();

        }else {
            System.out.println("披萨不存在");
        }


    }
}

//client调用

public class PizaaController {
    public static void main(String[] args) {
        OrderPizza orderPizza = new OrderPizza();
        orderPizza.doPizaOrder("bj");

    }
}

6.抽象工厂(简单+工厂方法) 写一个接口抽象最大的工厂
//如图14抽象工厂模式
请添加图片描述

//核心代码 抽象接口的工厂类

    public interface AbsFactory {
	//让下面的工厂子类来 具体实现
	public Pizza createPizza(String orderType);
}
  //抽象工厂的子工厂
public class BJFactory implements AbsFactory {

	@Override
	public Pizza createPizza(String orderType) {
		System.out.println("~使用的是抽象工厂模式~");
		// TODO Auto-generated method stub
		Pizza pizza = null;
		if(orderType.equals("cheese")) {
			pizza = new BJChinesePiza();
		} else if (orderType.equals("pepper")){
			pizza = new BJPepperPiza();
		}
		return pizza;
	}

}
public class LDFactory implements AbsFactory {

	@Override
	public Pizza createPizza(String orderType) {
		System.out.println("~使用的是抽象工厂模式~");
		Pizza pizza = null;
		if (orderType.equals("chinese")) {
			pizza = new LDChinesePiza();
		} else if (orderType.equals("pepper")) {
			pizza = new LDPepperPiza();
		}
		return pizza;
	}

}
     //下单类聚合工厂
public class OrderPizza {

	AbsFactory factory;

	// 构造器
	public OrderPizza(AbsFactory factory) {
		setFactory(factory);
	}

	private void setFactory(AbsFactory factory) {
		Pizza pizza = null;
		String orderType = ""; // 用户输入
		this.factory = factory;
		do {
			orderType = getType();
			// factory 可能是北京的工厂子类,也可能是伦敦的工厂子类
			pizza = factory.createPizza(orderType);
			if (pizza != null) { // 订购ok
				pizza.prepare();
				pizza.bake();
				pizza.cut();
				pizza.box();
			} else {
				System.out.println("订购失败");
				break;
			}
		} while (true);
	}

	// 写一个方法,可以获取客户希望订购的披萨种类
	private String getType() {
		try {
			BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
			System.out.println("input pizza 种类:");
			String str = strin.readLine();
			return str;
		} catch (IOException e) {
			e.printStackTrace();
			return "";
		}
	}
}
//调用创建订单测试类
public class PizzaStore {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//new OrderPizza(new BJFactory());
		new OrderPizza(new LDFactory());
	}

}

7.使用简单工厂的jdk Calendar类里的getInstance方法的createCalendar方法 的switch case工厂不一定是要有 factory命名的,只要看到批量出现new关键字可能是工厂模式
//要依赖抽象(不要依赖具体实现的类) ,下面是源代码

public static Calendar getInstance(TimeZone zone)
{
    return createCalendar(zone, Locale.getDefault(Locale.Category.FORMAT));
}

public static Calendar getInstance(Locale aLocale)
{
    return createCalendar(TimeZone.getDefault(), aLocale);
}

/**
 * Gets a calendar with the specified time zone and locale.
 * The <code>Calendar</code> returned is based on the current time
 * in the given time zone with the given locale.
 *
 * @param zone the time zone to use
 * @param aLocale the locale for the week data
 * @return a Calendar.
 */
public static Calendar getInstance(TimeZone zone,
                                   Locale aLocale)
{
    return createCalendar(zone, aLocale);
}

private static Calendar createCalendar(TimeZone zone,
                                       Locale aLocale)
{
    CalendarProvider provider =
        LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale)
                             .getCalendarProvider();
    if (provider != null) {
        try {
            return provider.getInstance(zone, aLocale);
        } catch (IllegalArgumentException iae) {
            // fall back to the default instantiation
        }
    }

    Calendar cal = null;

    if (aLocale.hasExtensions()) {
        String caltype = aLocale.getUnicodeLocaleType("ca");
        if (caltype != null) {
            switch (caltype) {  //批量创建
            case "buddhist":
            cal = new BuddhistCalendar(zone, aLocale);
                break;
            case "japanese":
                cal = new JapaneseImperialCalendar(zone, aLocale);
                break;
            case "gregory":
                cal = new GregorianCalendar(zone, aLocale);
                break;
            }
        }
    }
    if (cal == null) {
        // If no known calendar type is explicitly specified,
        // perform the traditional way to create a Calendar:
        // create a BuddhistCalendar for th_TH locale,
        // a JapaneseImperialCalendar for ja_JP_JP locale, or
        // a GregorianCalendar for any other locales.
        // NOTE: The language, country and variant strings are interned.
        if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {
            cal = new BuddhistCalendar(zone, aLocale);
        } else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"
                   && aLocale.getCountry() == "JP") {
            cal = new JapaneseImperialCalendar(zone, aLocale);
        } else {
            cal = new GregorianCalendar(zone, aLocale);
        }
    }
    return cal;
}

8.原型模式prototype(对象的复制)(如果要复制一个对象的所有信息给其他对象,必须一一赋值他的信息 效率低) 大圣拔毛A变出多个大圣
如原理图 15原型类uml原理图
请添加图片描述
//克隆羊案例(写一个羊的实体类,在测试方法new 一个羊,其他羊复制他的信息)传统浅拷贝写法
//java使用 类实现 Cloneable 覆盖Object的clone()方法???

     protected Object clone(){
         Sheep sheep=null; //如果羊没有被创建不能被克隆
         sheep=(Sheep)super.clone();

        return sheep;



   } 
    //使用,如果修改属性 不会修改代码,对比对象不是同一个
                  Sheep sheep=new  Sheep("tom","黑色")
                 Sheep sheep1=(Sheep)sheep.clone();

9.原型模式
缺点: 每个类必须配备一个克隆方法,但是对已有类修改违反了ocp原则
//如果羊类里面有个羊(朋友)的对象会不会拷贝? 会,但是指向原来类的赋值的对象(浅拷贝) hashcode一样的
//传统方案实现

 public class testA {
    public static void main(String[] args) {
        //Sheep的朋友还是属于一个同一个hashcode,所以是浅拷贝
        Sheep sheep = new Sheep("tom",11);
        sheep.setFriend(new Sheep("aa",11));
        Sheep friend = sheep.getFriend();
        System.out.println(friend.hashCode());
        Sheep sheep1 = new Sheep(sheep.getName(),sheep.getAge());
        sheep1.setFriend(new Sheep("aa",11));
        System.out.println(sheep.getFriend().hashCode());
        System.out.println(sheep);
        System.out.println(sheep1);


    }
}

//深拷贝, 要对他的所有成员进行拷贝,是引用类型的话要创建新空间进行拷贝
//实现方法1 实现 Cloneable 重写克隆方法,得到类的成员对象单独处理

         protected Object clone(){
         Sheep sheep=null; //如果羊没有被创建不能被克隆
         //对基本数据类型和String进行拷贝
         //对引用类型单独处理,调用引用类型的clone方法
         //子类hashcode和复制的对象的不一样
         sheep=(Sheep)super.clone();
          try{ //必须需要,因为会递归调用,不然报空指针
            sheep.friend=(Sheep)sheep.friend.clone();
        }catch (Exception e){
            System.out.println(e.getMessage());
        }

        return sheep;
   }   
 //方式2(推荐使用) 实现 Serializable 使用对象序列化和反序列化(使用对象流) 可以批量处理成员对象

-----完整代码------

public class Sheep implements Cloneable, Serializable {
    private String name;
    private Integer age;
    private Sheep friend;

    public Sheep(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Sheep getFriend() {
        return friend;
    }

    public void setFriend(Sheep friend) {
        this.friend = friend;
    }

    //方式1 需要Cloneable
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Sheep sheep=null;
        sheep=(Sheep)super.clone();
        System.out.println("aa"+sheep);
        try{
            sheep.friend=(Sheep)friend.clone();
        }catch (Exception e){
            System.out.println(e.getMessage());
        }


        return sheep;
    }

    //方式2 需要Serializable
    public Sheep copyObject() {
        //创建流对象
        ByteArrayOutputStream bos = null;
        ObjectOutputStream oos = null;
        ByteArrayInputStream bis = null;
        ObjectInputStream ois = null;

        try {

            //序列化,对象变成二进制流,通过对象流写入
            bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            oos.writeObject(this); //当前这个对象以对象流的方式输出

            //反序列化,把二进制变成变成对象流
            bis = new ByteArrayInputStream(bos.toByteArray());
            ois = new ObjectInputStream(bis);
            Sheep copyObj = (Sheep) ois.readObject();

            return copyObj;

        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
            return null;
        } finally {
            //关闭流
            try {
                bos.close();
                oos.close();
                bis.close();
                ois.close();
            } catch (Exception e2) {
                // TODO: handle exception
                System.out.println(e2.getMessage());
            }


        }
    }

    @Override
    public String toString() {
        return "Sheep{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", friend=" + friend +
                '}';
    }
}

-----测试------

public class testB {
    public static void main(String[] args) throws CloneNotSupportedException {
        //方式1
        Sheep sheep = new Sheep("tom",11);
        sheep.setFriend(new Sheep("jerry",12));
        Sheep friend1 = sheep.getFriend();
        System.out.println("复制前"+friend1.hashCode());

        Sheep clone = (Sheep) sheep.clone();
        Sheep friend = clone.getFriend();
        System.out.println("复制后"+friend.hashCode());


        //测试方式二
        System.out.println("方式2--------------");
        Sheep sheep3 = new Sheep("tom",12);
        sheep3.setFriend(new Sheep("jerry",12));
        System.out.println(sheep3);
        System.out.println(sheep3.hashCode());
        Sheep friend2 = sheep3.getFriend();
        System.out.println(friend2.hashCode());
        System.out.println(sheep3.hashCode());

        Sheep sheep4 = sheep3.copyObject();
        System.out.println(sheep4);
        System.out.println(sheep4.hashCode());
        Sheep friend3 = sheep4.getFriend();
        System.out.println(friend3.hashCode());
        System.out.println(sheep4.hashCode());


    }
}

10.原型模式 spring代码创建bean(beans.xml里面的定义bean的scope=“prototype”) 和getbean判断是否为原型对象
//代码 beans.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">


    <!-- 这里我们的 scope="prototype" 即 原型模式来创建 -->
    <bean id="id01" class="com.atguigu.spring.bean.Monster"
          scope="prototype"/>


</beans>
   //getBean方法
public class ProtoType {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
		// 获取monster[通过id获取monster]
		Object bean = applicationContext.getBean("id01");
		System.out.println("bean" + bean); // 输出 "牛魔王" .....
		
		Object bean2 = applicationContext.getBean("id01");
		
		System.out.println("bean2" + bean2); //输出 "牛魔王" .....

		System.out.println(bean == bean2); // false
		
		// ConfigurableApplicationContext
	}

}
//追到AbstactApplicationContext的getBean
    public Object getBean(String name) throws BeansException {
        this.assertBeanFactoryActive();
        return this.getBeanFactory().getBean(name);
    }
进入this.getBeanFactory().getBean(name); 方法的AbstractBeanFactory类 的this.doGetBean
具体实现有 } else if (mbd.isPrototype()) {  //会去创建一个hashcode不一样的对象,getBean每次得到了不同的对象

11.建造者模式(builder)(生成器模式)

  1. 什么是?
    1.有固定步骤的但是过程不同可以用
    2.4个角色 Product(产品角色) Builder(抽象建造者) ConcreteBuilder(具体建造者) Director(指挥者) 构造一个Builder接口的对象(调用抽象建造过程)
    图 16建造者模式原理图 请添加图片描述

  2. 解决了什么? 加了抽象类做个缓冲层, 产品和产品建筑过程解耦

  3. 怎么做? 建房子例子

 //传统方式 实体类和建造过程耦合度高
public abstract class House {
    private String name;
    private Integer age;
    public abstract void base();
    public abstract void block();
    public abstract void roofed();
    public void build(){
        this.base();
        this.block();
        this.roofed();
    }



}
public class NormalHouse extends House{
    @Override
    public void base() {
        System.out.println("普通打地基");
    }

    @Override
    public void block() {
        System.out.println("普通砌10cm砖块");
    }

    @Override
    public void roofed() {
        System.out.println("普通盖屋顶");
    }


}
//测试,要增加一个其他类型的楼房,需要再次继承 所有成员和成员方法
public class TestBuildClient {
    public static void main(String[] args) {
        NormalHouse normalHouse = new NormalHouse();
        normalHouse.build();
    }
}

//改进方式 图 17.建造者模式代码实现

    //创建没有方法的成员实体

请添加图片描述

public class House {
    private String name;
    private Integer age;
    private String type;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "House{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", type='" + type + '\'' +
                '}';
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

//2.创建builder抽象类专门来写 创建过程,并且聚合实体

public abstract class HouseBuilder {

    protected House house=new House();
    public abstract void base();
    public abstract void block();
    public abstract void roofed();
    public  House build(){
       return house;
    };



}

//3.创建他的子类 实现方法并且可以操作实体的成员

public class ModernHouse extends HouseBuilder {

    @Override
    public void base() {
        this.house.setType("摩天大楼"); //自己可以操作实体成员
        System.out.println("摩天大楼打地基");
    }

    @Override
    public void block() {
        System.out.println("摩天大楼砌20cm砖块");
    }

    @Override
    public void roofed() {
        System.out.println("摩天大楼盖透明屋顶");
    }
}

//4.创建指挥者调用全部 的创建过程,构造方法传入要构造房子的类型

public class HouseDirector {
    HouseBuilder houseBuilder;
    HouseDirector(HouseBuilder houseBuilder){
        this.houseBuilder=houseBuilder;

    }

    public void setHouseBuilder(HouseBuilder houseBuilder) {
        this.houseBuilder = houseBuilder;
    }
    public House constructHouse(){
        houseBuilder.base();
        houseBuilder.block();;
        houseBuilder.roofed();
        return houseBuilder.build();
    }

}

//Client使用 指挥者

public class Client {
    public static void main(String[] args) {
        HouseDirector houseDirector = new HouseDirector(new NormalHouse());
        House house = houseDirector.constructHouse();
        System.out.println(house);

        HouseDirector houseDirector1 = new HouseDirector(new ModernHouse());
        House house1 = houseDirector1.constructHouse();
        System.out.println(house1);
    }
}

12.jdk建造者StringBuilder(不是完全的建造者,jdk作者太强了,设计模式还没有出来,就有代码了)
的Appendable接口的多个append方法(抽象)(builder)

   AbstractStringBuilder实现了Appendable方法,不能实例化 (建造者)
   StringBuilder充当了指挥者,也充当了具体的建造者
public class BuilderSourceCode {
    public static void main(String[] args) {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("ngs");
        stringBuilder.insert(0,"aaa");
        System.out.println(stringBuilder);
    }
}
//StringBuilder
    @Override
    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }
//建造者 AbstractStringBuilder
    public AbstractStringBuilder append(String str) {
        if (str == null)
            return appendNull();
        int len = str.length();
        ensureCapacityInternal(count + len);
        str.getChars(0, len, value, count);
        count += len;
        return this;
    }

13.建造者注意点

1.符合开闭原则
2.如果产品差异太大,不适合用
3.抽象工厂(是创建不同类的产品) 建造者(是相同产品,但是组装的不同步骤[蓝图])

14.适配器模式

  1. 是什么
    1.(为了兼容性,类/接口转为另外一个类/接口)比如如果缺少参数不能调用, 电源适配器适配不同规格的插座
    2.用户看不到适配者,是解耦的
    3.几个角色 dist(目标)<-适配器Adapter<-src(source)被适配者
    //没有适配器的代码
public class Phone {
    Voltage5V v;
   Phone(Voltage5V v){
        this.v=v;
   }
    void charge(){
        if(v.out5V()==5){
            System.out.println("充电成功");
        }else {
            System.out.println("充电失败");
        }

    }
}
//220v类输出220v电压
public class Voltage220V {
    int output(){
        return 220;
    }
}
//直接在5V转220V增加了耦合
//需要从220转为5v
public class Voltage5V {
    Voltage220V v;
    Voltage5V(Voltage220V v){
        this.v=v;
    }

    int out5V(){
        if (v.output()==220){
            int out5=v.output()/44;
            return out5;
        }
        return 0;
    }



}

//这里我觉得我把charge方法传入电压比较合适,不然每次使用手机都要传入充电的对象

public class testPhone {
    public static void main(String[] args) {
        Voltage5V voltage5V = new Voltage5V(new Voltage220V()); //这里同时看到220v和5v类
        Phone phone = new Phone(voltage5V);
        phone.charge();
    }
}

2.类适配器(继承 类方式给到) 图18类适配器
请添加图片描述

  1. 需要继承src类(尽量不用继承),dst必须是接口
  2. src类的方法在Adapter使用,增加了使用成本
  3. adapter类继承src类可以重写方法,提高了灵活性
//手机类
public class Phone {


    void charge(IVoltage5V v){
        if(v.output5V()==5){
            System.out.println("充电成功");
        }else {
            System.out.println("充电失败");
        }

    }
}
    //220v类输出220v电压
public class Voltage220V {
    int output220V(){
        return 220;
    }
}
 //引发了一个思考,220v类是具体的,5v是接口抽象的(因为他可以通过220v转换过来,所以不用写,让适配器类去实现代码)
 public interface IVoltage5V {
	public int output5V();
}          
//适配器类,主要继承和实现两个功能,相当于合并类的功能
public class IVoltage5VAdapter extends Voltage220V implements IVoltage5V {

    @Override
    public int output5V() {
        int out=output220V()/44;
        if (out==5){
            return 5;
        }
        return 0;
    }
}
//测试
public class Client {
    public static void main(String[] args) {
        Phone phone = new Phone();
        phone.charge(new IVoltage5VAdapter()); //客户端看不到220这个类了,就是解耦了
    }
}
    3.对象适配器(对象方式给到适配器)(类适配器改继承为聚合关系,记得对象判空)  uml图 19对象适配器
    
    //类适配器代码的基础上,改适配器类继承为聚合

//适配器类,主要继承和实现两个功能,相当于合并功能

public class IVoltage5VAdapter   implements IVoltage5V { //去继承,继承违反里氏定律
    Voltage220V v;//改继承为聚合关系
    IVoltage5VAdapter(Voltage220V v){
        this.v=v;
    }
    @Override
    public int output5V() {
        int dist=0;
        System.out.println(v);
        if (null!=v){  //必须进行判空,以免聚合的对象不存在
            dist=v.output220V()/44;
            if (dist==5){

                return dist;
            }
        }

        return dist;
    }
}
   //改测试代码
public class Client {
    public static void main(String[] args) {
        Phone phone = new Phone();
        phone.charge(new IVoltage5VAdapter(new Voltage220V()));
    }
}

4.接口(缺省)适配器模式(实现)(抽象类实现接口空实现)(不想实现接口的全部方法,抽象类空实现方法,使用匿名内部类重写)
图 20接口适配器
请添加图片描述

//假设我们这个手机是快充的,可以适配很多个 5v 7v 20v电压的

public class Phone {


    void charge(IVoltageAny v){
        if(v.output5V()==5){
            System.out.println("充电成功"+v.output5V()+"V");
        }else if(v.output7V()==7){
            System.out.println("充电成功"+v.output7V()+"V");
        }else if(v.output20V()==20){
            System.out.println("充电成功"+v.output20V()+"V");
        }else {
            System.out.println(v.output5V());
            System.out.println("充电失败");
        }

    }
}
//220v类输出220v电压
public class Voltage220V {
    int output220V(){
        return 220;
    }
}
//转换任何类型的电压
public interface IVoltageAny {
	public int output5V();
	public int output7V();
	public int output20V();

}
//抽象类可以空实现后覆盖
public abstract class IVoltageAdapter   implements IVoltageAny {


    @Override
    public int output5V() {
        return 0;
    }

    @Override
    public int output7V() {
        return 0;
    }

    @Override
    public int output20V() {
        return 0;
    }

}
//覆盖空实现
public class Client {
    public static void main(String[] args) {
       Phone phone = new Phone();
      phone.charge(new IVoltageAdapter() {
          @Override
          public int output5V() {
              int dist=0;
              Voltage220V voltage220V = new Voltage220V();
              if (null!=voltage220V){
                  dist=voltage220V.output220V()/44;
                  if (dist==5){
                      return dist;
                  }

              }
              return dist;
          }


      });
        phone.charge(new IVoltageAdapter() {
            @Override
            public int output20V() {
                int dist=0;
                Voltage220V voltage220V = new Voltage220V();
                if (null!=voltage220V){
                    dist=voltage220V.output220V()/11;
                    if (dist==20){
                        return dist;
                    }

                }
                return dist;
            }


        });

    }
}

15.springmvc的接口适配器 DispatchServlet类的HandlerAdapter
图21适配器springmvc源代码
请添加图片描述

//源代码片段,适配器是通过判断String然后getBean得到controller的
//DispatchServlet类

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		HttpServletRequest processedRequest = request;
		HandlerExecutionChain mappedHandler = null;
		boolean multipartRequestParsed = false;

		WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

		try {
			ModelAndView mv = null;
			Exception dispatchException = null;

			try {
				processedRequest = checkMultipart(request);
				multipartRequestParsed = processedRequest != request;

				// Determine handler for the current request.
				mappedHandler = getHandler(processedRequest);
				if (mappedHandler == null || mappedHandler.getHandler() == null) {
					noHandlerFound(processedRequest, response);
					return;
				}

				//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!核心代码
				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); 

				// Process last-modified header, if supported by the handler.
				String method = request.getMethod();
				boolean isGet = "GET".equals(method);
				if (isGet || "HEAD".equals(method)) {
					long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
					if (logger.isDebugEnabled()) {
						String requestUri = urlPathHelper.getRequestUri(request);
						logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);
					}
					if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
						return;
					}
				}

				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}

				try {
					// Actually invoke the handler.
					mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
				}
				finally {
					if (asyncManager.isConcurrentHandlingStarted()) {
						return;
					}
				}

				applyDefaultViewName(request, mv);
				mappedHandler.applyPostHandle(processedRequest, response, mv);
			}
			catch (Exception ex) {
				dispatchException = ex;
			}
			processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
		}
		catch (Exception ex) {
			triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
		}
		catch (Error err) {
			triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
		}
		finally {
			if (asyncManager.isConcurrentHandlingStarted()) {
				// Instead of postHandle and afterCompletion
				mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
				return;
			}
			// Clean up any resources used by a multipart request.
			if (multipartRequestParsed) {
				cleanupMultipart(processedRequest);
			}
		}
	}
//核心代码的得到适配器方法 的supports方法
	protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
		for (HandlerAdapter ha : this.handlerAdapters) {
			if (logger.isTraceEnabled()) {
				logger.trace("Testing handler adapter [" + ha + "]");
			}
			if (ha.supports(handler)) {
				return ha;
			}
		}
		throw new ServletException("No adapter for handler [" + handler +
				"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
	}
    //适配器接口
public interface HandlerAdapter {

                  //最后修改的handler
	long getLastModified(HttpServletRequest request, Object handler);

}

//手写模拟源代码运行过程
1.写Controller接口和不同实现类(空实现因为具有语义化) 来处理请求
//多种Controller实现

public interface Controller {

}

class HttpController implements Controller {
	public void doHttpHandler() {
		System.out.println("http...");
	}
}

class SimpleController implements Controller {
	public void doSimplerHandler() {
		System.out.println("simple...");
	}
}

class AnnotationController implements Controller {
	public void doAnnotationHandler() {
		System.out.println("annotation...");
	}
}
     2.写适配器接口和他们的实现类(有、support适配方法和handle处理请求方法)
///定义一个Adapter接口 
public interface HandlerAdapter {
	public boolean supports(Object handler);

	public void handle(Object handler);
}

// 多种适配器类

class SimpleHandlerAdapter implements HandlerAdapter {

	public void handle(Object handler) {
		((SimpleController) handler).doSimplerHandler();
	}

	public boolean supports(Object handler) {
		return (handler instanceof SimpleController);
	}

}

class HttpHandlerAdapter implements HandlerAdapter {

	public void handle(Object handler) {
		((HttpController) handler).doHttpHandler();
	}

	public boolean supports(Object handler) {
		return (handler instanceof HttpController);
	}

}

class AnnotationHandlerAdapter implements HandlerAdapter {

	public void handle(Object handler) {
		((AnnotationController) handler).doAnnotationHandler();
	}

	public boolean supports(Object handler) {

		return (handler instanceof AnnotationController);
	}

}
    
     3.创建一个List放适配器类, 
      doDispatch调用适配器方法getHandler的supports方法使用instanceof 判断传入controller是否是controller对象的实例,返回转换的controller的调用doHttpHandler的结果
     public class DispatchServlet {

	public static List<HandlerAdapter> handlerAdapters = new ArrayList<HandlerAdapter>();

	public DispatchServlet() {
		handlerAdapters.add(new AnnotationHandlerAdapter());
		handlerAdapters.add(new HttpHandlerAdapter());
		handlerAdapters.add(new SimpleHandlerAdapter());
	}

	public void doDispatch() {

		// 此处模拟SpringMVC从request取handler的对象,
		// 适配器可以获取到希望的Controller
		 HttpController controller = new HttpController();
		// AnnotationController controller = new AnnotationController();
		//SimpleController controller = new SimpleController();
		// 得到对应适配器
		HandlerAdapter adapter = getHandler(controller);
		// 通过适配器执行对应的controller对应方法
		adapter.handle(controller);

	}

	public HandlerAdapter getHandler(Controller controller) {
		//遍历:根据得到的controller(handler), 返回对应适配器
		for (HandlerAdapter adapter : this.handlerAdapters) {
			if (adapter.supports(controller)) {
				return adapter;
			}
		}
		return null;
	}

	public static void main(String[] args) {
		new DispatchServlet().doDispatch(); // http...
	}

}
         
          //思考我直接调用controller的方法不就好了,为什么还要脱裤子放屁?
          //答案: 1.主要是为了软件的长远增加代码考虑,如果增加多几个controller,岂不是要增加几个判断条件判断是哪个controller然后调用使代码复杂 不好维护
         //2.这样做直接 add适配器类,不用改依赖的代码,增加一个controller和adapter(这是写代码的套路)
           	public DispatchServlet() {
		handlerAdapters.add(new AnnotationHandlerAdapter());
		handlerAdapters.add(new HttpHandlerAdapter());
		handlerAdapters.add(new SimpleHandlerAdapter());
                               handlerAdapters.add(new   XXXAdapter());
	}

          

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/698528.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unity 提取并拷贝Hierarchy路径

提取并拷贝Hierarchy路径 &#x1f354;效果&#x1f96a;食用 &#x1f354;效果 &#x1f96a;食用 &#x1f4a1;.导入包后直接选中GameObject右键选择&#xff1a;复制Hierarchy路径 &#x1f4a1;.快捷键Ctrl V 即可粘贴路径

SurfaceFlinge/InputFlinger分析-android画面缩放后依然点击正常原理分析

hi&#xff0c;粉丝朋友们&#xff1a; 这两天刚好在做自由窗口相关国内需求&#xff0c;刚好遇到一个疑惑&#xff0c;那就是画面进行缩放后发现依然触摸画面可以正常反映问题。 具体疑惑背景 疑问点如下&#xff1a; 坐标是针对屏幕的&#xff0c;按钮也是相对Activity的&…

【SPI】STM32 SPI 双机通信,SPI从机模式使用

文章目录 一、SPI主机配置二、SPI从机配置三、双机通信1 轮询中断&#xff08;低速&#xff09;2 轮询DMA&#xff08;低速&#xff09;3 DMADMA&#xff08;高速&#xff09;4 开启CRC校验&#xff08;自选&#xff09; 四、遇到的问题1 高速使用时&#xff0c;程序卡死&#…

JavaScript 原型与原型链

所有的 JavaScript 对象都会从一个 prototype&#xff08;原型对象&#xff09;中继承属性和方法&#xff1a; Date 对象从 Date.prototype 继承。 Array 对象从 Array.prototype 继承。 所有 JavaScript 中的对象都是位于原型链顶端的 Object 的实例。 JavaScript 对象有一个指…

【C#】代码解析--打印数据集

系列文章 【C#】编号生成器&#xff08;定义单号规则、固定字符、流水号、业务单号&#xff09; 本文链接&#xff1a;https://blog.csdn.net/youcheng_ge/article/details/129129787 【C#】日期范围生成器&#xff08;开始日期、结束日期&#xff09; 本文链接&#xff1a;h…

LangChain:LLM应用程序开发(中)——文档问答、评估、Agents(代理)

文章目录 四、文档问答4.1 快速入门4.2 逐步实现4.3 其它方法 五、评估5.1 创建QA app5.2 生成测试数据点5.2.1 Hard-coded examples5.2.2 LLM-Generated examples 5.3 link chain debug手动评估5.4 LLM assisted evaluation5.5 LangChain Evaluation platform 六、Agents&…

704.二分查找

一、题目 二、代码 #define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> int search(int* nums, int numsSize, int target) {int left 0;int right numsSize - 1;while (left < right) {int middle (left right) / 2;if (target > nums[middle]) {left m…

pip3 报错 distribution was not found and is required by the application

环境&#xff1a; centos 8 &#xff0c; pyhton3.6 背景&#xff1a; 升级python3.6 至 python3.10后&#xff0c; pip3安装包报错&#xff1a; pkg_resources.VersionConflict: (pip 21.2.4 (/usr/local/python3/lib/python3.10/site-packages), Requirement.parse(pip23.…

Linux:scp命令

1.介绍 scp命令是cp命令的升级版&#xff0c;即&#xff1a;ssh cp&#xff0c;通过SSH协议完成文件的复制。其主要的功能就是&#xff1a;在不同的Linux服务器之间&#xff0c;通过SSH协议互相传输文件。只要知晓服务器的账户和密码&#xff08;或密钥&#xff09;&#xff0c…

美光之后,韩国存储芯片也将成为输家,将损失千亿美元

美光很可能将完全丧失中国的企业市场&#xff0c;随着影响的扩大&#xff0c;韩国存储芯片或也将因美光的影响而蒙受巨大的损失&#xff0c;预计损失最高可能达到千亿美元&#xff0c;韩国存储芯片的老大地位也将因此动摇。 美光日前对媒体披露的数据指出因中国的安全审查&…

GitHub下的项目有pom.xml但右侧没有Maven问题

1.可以使用idea自带功能将pom.xml作为Maven导入 双击shift&#xff0c;输入Maven点击Add Maven Projects注意&#xff1a;在settings中将Maven先配置好&#xff0c;我使用的是自己设置的Maven仓库而不是idea自动部署在C盘的仓库

SQL Server数据库 -- 表的创建与管理

文章目录 一、数据表的组成二、创建数据表 表的创建表的查看表的增加表的修改表的删除、三、表的架构操作四、总结 前言 上次博客写到了数据库的创建与管理&#xff0c;但是创建的库里面什么东西都没有&#xff0c;现在我们需要在库里面添加数据表内容 一、数据表的组成 在创…

美好未来“一束光”儿童安全教育项目在四川泸定正式启动

6月26日&#xff0c;由中华少年儿童慈善救助基金会和北京臻爱公益基金会共同发起的美好未来计划“一束光”儿童安全教育公益项目启动仪式&#xff0c;在四川省甘孜藏族自治州泸定县贡嘎山片区寄宿制学校举行。 出席本次启动仪式活动的嘉宾有&#xff1a;中华少年儿童慈善救助基…

基于“SRP模型+”多技术融合在生态环境脆弱性评价模型构建、时空格局演变分析与RSEI指数的生态质量评价及拓展应用

目录 ​第一章 生态环境脆弱性评价内涵及基于文献可视化方法研究热点分析 第二章 数据来源及预处理 第三章 生态环境脆弱性评价模型构建 第四章 生态环境脆弱性时空格局演变分析 第五章 生态环境脆弱性时空格局演变驱动机制分析 第六章 基于 RSEI 指数的生态质量评价 第…

js输入一个字符串,打印出该字符串中,所有字符的排列组合(超清晰)

一、题目 输入一个字符串&#xff0c;打印出该字符串中&#xff0c;所有字符的排列组合。 输入&#xff1a;abc 输出&#xff1a;[abc, acb, bca, bac, cab, cba] 二、思路 回溯算法。其核心思想是通过递归的方式进行深度优先搜索&#xff0c;当发现当前的选择不符合要求时…

机器学习技术:如何使用交叉验证和ROC曲线提高疾病预测的准确性和效率?

一、引言 随着机器学习的普及&#xff0c;评估模型的性能越来越重要。交叉验证和ROC曲线是两种常见的评估模型性能的方法。本文将介绍这两种方法的基本原理和应用场景&#xff0c;并结合实际案例和技术实践&#xff0c;讲解如何使用交叉验证和ROC曲线来提高机器学习模型的性能…

mongodb原理

一&#xff1a;MongoDB的优点和缺点 优点 面向文档存储(类JSON数据模式简单而强大)动态查询全索引支持,扩展到内部对象和内嵌数组查询记录分析快速,就地更新高效存储二进制大对象 (比如照片和视频)复制和故障切换支持Auto- Sharding自动分片支持云级扩展性MapReduce 支持复杂…

chatgpt赋能python:Python选择对话框:简化用户操作的实用工具

Python选择对话框&#xff1a;简化用户操作的实用工具 在Python编程领域中&#xff0c;常常需要与用户进行交互&#xff0c;以便更好地控制程序运行结果。而选择对话框则是一种简化用户操作的实用工具&#xff0c;可避免用户输入错误或步骤繁琐的问题。在本篇文章中&#xff0…

【UE】一个需求案例掌握Timeline和插值Lerp

文章目录 问题背景结论先行timeline和lerp原理使用timelinelerp实现相机平滑跟随BUG猜想验证和解决 问题背景 今天用timelinelerp插值做了一个相机平滑跟随的需求 如果只是要求跟随&#xff0c;直接在tick中把相机位置设置成角色位置就可以 但希望有一个相机滞后角色一点点的…

如何避免ChatGPT,ChatGLM这类大语言模型胡说八道

“ ChatGPT&#xff0c;ChatGLM这类大语言模型一本正经的胡说八道&#xff0c;可能也是它创造性回答的部分。那么谁来判断它在编造无中生有的内容&#xff1f;恐怕只有人才能判断。模型怎么会产生幻觉&#xff0c;我们又怎么避免它产生幻觉&#xff1f;” 01 — 昨天体验了国产…