设计模式

设计模式(一)

设计模式概述

设计模式_第1张图片

设计模式的几个要素

在这里插入图片描述

设计原则(六大原则)

单一职责原则
开闭原则
里氏替换原则
依赖注入原则
接口分离原则
迪米特原则

设计模式的分类(三种分类)

设计模式_第2张图片
设计模式_第3张图片
设计模式_第4张图片

单例设计模式

设计模式_第5张图片

1.饿汉式单例

Singleton.java

package demo1;
/*
 * 单例设计模式的演示
 * 
 * 单例模式的特点:
 * 		1.单例类只能有一个实例
 * 		2.单例类必须自己创建自己的唯一实例
 * 		3.单例类必须给所有其他对象提供这一实例
 */
public class Singleton {

/*-----------------------------创建Singleton实例------------------------------------*/
	
//	饿汉式,因为很饿,所以直接创建实例,然后公共方法返回本对象
	private static Singleton singleton = new Singleton();
	
//	私有化构造,防止其他类能够自己创建实例
	private Singleton(){
		
	}
	
//	给外界提供公共方法来创建对象
	public static Singleton getInstance(){
		return singleton;
	}
}

TestSingleto.java

package demo1;

public class TestSingleTon {
	public static void main(String[] args) {
		
/*-----------------------------创建Singleton实例------------------------------------*/
//		Singleton singleton1 = new Singleton();
//		Singleton singleton2 = new Singleton();
//		Singleton singleton3 = new Singleton();
		
//		调用方法创建实例,虽然调用了三次方法,但是创建的对象却是同一个
		Singleton singleton1 = Singleton.getInstance();
		Singleton singleton2 = Singleton.getInstance();
		Singleton singleton3 = Singleton.getInstance();
		
		System.out.println(singleton1);
		System.out.println(singleton2);
		System.out.println(singleton3);
	}
}
2.懒汉式单例

Singleton.java

/*
 * 懒汉式:可能会发生线程安全问题,因为可能在getInstance方法之中创建了多个线程
 */
public class Singleton{
	
	private static Singleton singleton = null;
	
	//私有化构造,防止其他类能够自己创建实例
	private Singleton(){
		
	}
	
	//给外界提供公共方法来创建对象,为了防止线程安全问题,添加关键字synchronized
	//怎样的线程安全问题?在一个线程进入下面方法时没有创建实例执行了if语句,另一个线程同时进入显示没有实例继续if语句创建实例
	public static synchronized  Singleton getInstance(){
		if (singleton == null) {
			singleton = new Singleton();
		}
		return singleton;
	}
}

TestSingleto.java

package demo1;

public class TestSingleTon {
	public static void main(String[] args) {
		
/*-----------------------------创建Singleton实例------------------------------------*/
//		Singleton singleton1 = new Singleton();
//		Singleton singleton2 = new Singleton();
//		Singleton singleton3 = new Singleton();
		
//		调用方法创建实例,虽然调用了三次方法,但是创建的对象却是同一个
		Singleton singleton1 = Singleton.getInstance();
		Singleton singleton2 = Singleton.getInstance();
		Singleton singleton3 = Singleton.getInstance();
		
		System.out.println(singleton1);
		System.out.println(singleton2);
		System.out.println(singleton3);
	}
}
3.双重验证单例

Singleton.java

public class Singleton{
	
	private static Singleton singleton = null;
	
	//私有化构造,防止其他类能够自己创建实例
	private Singleton(){
		
	}
	
	//给外界提供公共方法来创建对象,为了防止线程安全问题,添加关键字synchronized
	//怎样的线程安全问题?在一个线程进入下面方法时没有创建实例执行了if语句,另一个线程同时进入显示没有实例继续if语句创建实例
	public static synchronized  Singleton getInstance(){
		if (singleton == null) {
			synchronized(Singleton.class){
				if(singleton == null){
					singleton = new Singleton();
				}
			}
		}
		return singleton;
	}
} 

TestSingleton.java

package demo1;

public class TestSingleTon {
	public static void main(String[] args) {
		
/*-----------------------------创建Singleton实例------------------------------------*/
//		Singleton singleton1 = new Singleton();
//		Singleton singleton2 = new Singleton();
//		Singleton singleton3 = new Singleton();
		
//		调用方法创建实例,虽然调用了三次方法,但是创建的对象却是同一个
		Singleton singleton1 = Singleton.getInstance();
		Singleton singleton2 = Singleton.getInstance();
		Singleton singleton3 = Singleton.getInstance();
		
		System.out.println(singleton1);
		System.out.println(singleton2);
		System.out.println(singleton3);
	}
}

设计模式(二)

原型模式

设计模式_第6张图片

下面的代码只是简单的复制

ICloneable.java

package demo2;

public class ICloneable {
	private String name;//姓名
	private int age;//年龄
	private String last;//上一家公司
	private String address;//公司地址
	private Number number;//电话
	
	/*个人信息*/
	public void setInfo(String name,int age,Number number){
		this.name = name;
		this.age = age;
		this.number=number;
	}
	
	/*工作经验*/
	public void setWeek(String last,String address){this.last = last; this.address = address;}
	
	/*查看简历*/
	public void show(){
		System.out.println("姓名:"+name+",年龄:"+age+",联系电话:"+number.getPhone());
		System.out.println("公司名称:"+last+",公司地址:"+address);
	}

	public String getName() {return name;}
	public void setName(String name) {this.name = name;}
	public int getAge() {return age;}
	public void setAge(int age) {this.age = age;}
	public String getLast() {return last;}
	public void setLast(String last) {this.last = last;}
	public String getAddress() {return address;}
	public void setAddress(String address) {this.address = address;}
	public Number getNumber() {return number;}
	public void setNumber(Number number) {this.number = number;}
	@Override
	public String toString() {
		return "ICloneable [address=" + address + ", age=" + age + ", last="
				+ last + ", name=" + name + ", number=" + number + "]";
	}
}

Number.java

package demo2;

public class Number {
	private String phone;
	public String getPhone() {
		return phone;
	}
	public void setPhone(String phone) {
		this.phone = phone;
	}
}

TestCloneable.java

package demo2;
/*
 * 下面的代码只是简单的复制,不是克隆,因为一个改变,全部改变
 */
public class TestICloneable {
	public static void main(String[] args) {
//		创建原型简历模板
		ICloneable clone = new ICloneable();
//		设置手机号
		Number number = new Number();
		number.setPhone("1234567889");
//		设置个人信息
		clone.setInfo("张三",17,number);
//		设置工作经验
		clone.setWeek("京东","东京");
		clone.show();
		
//		复制简历
		System.out.println("-----------------克隆一号----------------------");
		ICloneable clone2 = clone;
		Number number2 = new Number();
		number.setPhone("111111111");
		clone2.setInfo("李四", 12, number2);
		clone2.show();
		
		System.out.println("-----------------克隆二号----------------------");
		ICloneable clone3 = clone;
		clone3.show();
	}
}
要真正的实现克隆必须实现Cloneable接口,添加clone方法

在ICloneable.java中继承接口Cloneable,并重写clone方法

ublic class ICloneable implements Cloneable{
@Override
	protected Object clone() throws CloneNotSupportedException {
		return super.clone();
	}

将TestCloneable.java中的克隆语句修改如下

System.out.println("-----------------克隆一号----------------------");
ICloneable clone2 = (ICloneable) clone.clone();
Number number2 = clone2.getNumber();
number2.setPhone("123123");
clone2.setInfo("李四", 12, number2);
clone2.show();

System.out.println("-----------------克隆二号----------------------");
ICloneable clone3 = (ICloneable) clone.clone();
clone3.show();

运行结果如下

姓名:张三,年龄:17,联系电话:1234567889
公司名称:京东,公司地址:东京
-----------------克隆一号----------------------
姓名:李四,年龄:12,联系电话:1234567889
公司名称:京东,公司地址:东京
-----------------克隆二号----------------------
姓名:张三,年龄:17,联系电话:1234567889
公司名称:京东,公司地址:东京

克隆分为深克隆和浅克隆,上述是浅克隆,所以电话号码不变
设计模式_第7张图片
ICloneable.java添加下面代码,并且开头继承序列化

/*
	 * 深克隆:将对象重新组装,组成新的对象
	 * 
	 * 利用序列化将对象组装成序列,再将序列转换成对象
	 * 
	 * 将一个对象复制后,基本数据类型和引用类型重新创建
	 */
	public Object deepClone() throws Exception{
		ByteArrayOutputStream bos = new ByteArrayOutputStream();//声明一个临时空间
		ObjectOutputStream ooStream = new ObjectOutputStream(bos);
		ooStream.writeObject(this);//将当前对象序列化
		
		byte[] bs = bos.toByteArray();//构件字节数组
		ByteArrayInputStream bisArrayInputStream  = new ByteArrayInputStream(bs);//反序列化
		ObjectInputStream ois = new ObjectInputStream(bisArrayInputStream);//将从bisArrayInputStream读取的数据注入到ois之中
		return ois.readObject();//读取数据返回Object类型
		
	}
/*
 *  java.io.NotSerializableException: demo2.ICloneable,则需要添加序列化关键字Serializable
 */
public class ICloneable implements Cloneable,Serializable{
	private static final long serialVersionUID = 2269323637457452994L;

Number.java继续序列化

public class Number implements Serializable{
	
	private static final long serialVersionUID = 1L;//生成序列化版本ID

TestICloneable.java中复制简历部分改成如下
出现未知错误,导致运行结果不理想,具体看Java视频部分

复制简历
System.out.println("-----------------克隆一号----------------------");
ICloneable clone2 = (ICloneable) clone.deepClone();
Number number2 = clone2.getNumber();
number2.setPhone("111111111");
clone2.setInfo("李四", 12, number2);
clone2.show();

System.out.println("-----------------克隆二号----------------------");
ICloneable clone3 = (ICloneable) clone.deepClone();
Number number3 = clone3.getNumber();
number2.setPhone("2222222");
clone2.setInfo("小红", 11, number3);
clone3.setWeek("百度", "北京西二旗");
clone3.show();

模式设计(三)

工厂模式

设计模式_第8张图片

简单工厂
	一个抽象产品类可以派生出多个具体产品类。一个抽象工厂类可以创建多个具体产品类;

工厂方法
	一个抽象产品类可以派生多个具体产品类,一个抽象工厂类可以派生多个具体工厂类,每个具体工厂只能创建一个具体产品类实例;

抽象工厂
	多个抽象产品类,每个抽象产品类能派生多个具体产品类,一个抽象工厂类可以派生多个具体工厂类,每个具体工厂类可以创建多个具体
	产品类的实例;

简单工厂

设计模式_第9张图片

优点:客户端不需要负责对象的创建,从而明确了各个类的职责
缺点:如果有新的对象添加,那么就要修改工厂类,不利于后期的维护
package demo3;
/*
 * 具体产品类
 */
public class Cat implements Animal{
	@Override
	public void eat() {
		System.out.println("猫吃鱼");
	}
}
package demo3;
/*
 * 具体产品类
 */
public class Dog implements Animal{
	@Override
	public void eat() {
		System.out.println("狗吃骨头");
	}
}

package demo3;
/*
 * 抽象产品类
 */
public interface Animal {
	public void eat();
}
package demo3;
/*
 * 主要负责创建多个具体的产品类
 */
public class AnimalFactory {
	
//	//生产狗对象
//	public static Dog getDog(){
//		return new Dog();
//	}
//	
//	//生产猫对象
//	public static Cat getCat(){
//		return new Cat();
//	}
	
	public static Animal getAnimal(String name){
		if("dog".equals(name)){
			return new Dog();
		}else if ("cat".equals(name)) {
			return new Cat();
		}else {
			return null;
		}
	}
	
}

package demo3;

public class TestFctory {
	public static void main(String[] args) {
	/*	Dog dog = AnimalFactory.getDog();
		dog.eat();
		
		Cat cat = AnimalFactory.getCat();
		cat.eat();
		
		Dog dog2 = AnimalFactory.getDog();
		System.out.println(dog2);
		
		System.out.println(dog);
		System.out.println(cat);
	*/
		
		Animal animal = AnimalFactory.getAnimal("dog");
		animal.eat();
		Animal animal2 = AnimalFactory.getAnimal("cat");
		animal2.eat();
	}
}

工厂方法

设计模式_第10张图片
Animal.java

public interface Animal {public void eat();}/*抽象类*/

Factory.java

/*抽象工厂类*/
public interface Factory {
	public Animal createAnimal();
}

Dog.java

public class Dog implements Animal{
	@Override
	public void eat() {System.out.println("狗吃骨头");}
}

Cat.java

public class Cat implements Animal{
	@Override
	public void eat() {System.out.println("猫吃鱼");}
}

DogFactory.java

public class DogFactory implements Factory{
	@Override
	public Animal createAnimal() {
		return new Dog();
	}
}

CatFactory.java

public class CatFactory implements Factory{
	@Override
	public Animal createAnimal() {
		return new Cat();
	}
}

TestFactory.java

public class TestFactory {
	public static void main(String[] args) {
		
		Factory factory = new DogFactory();
		Animal dog = factory.createAnimal();
		dog.eat();
		
		Factory factory2 = new CatFactory();
		Animal cat = factory2.createAnimal();
		cat.eat();
	}
}

抽象工厂

多个抽象产品类,每个抽象产品类能派生多个具体产品类;
一个抽象工厂类可以派生多个具体工厂类,每个具体工厂类可以创建多个具体产品类的实例;

抽象产品类:水果、蔬菜 → → → 具体产品类:北方水果、南方水果、北方蔬菜、南方蔬菜
抽象工厂类:产品工厂 → → → 具体工厂:北方产品工厂、南方产品工厂

设计模式_第11张图片
下述几个水果蔬菜文件,抽象水果蔬菜类派生具体水果工厂类

package demo5;
//水果抽象接口
public interface Fruit {
	public void fruitInfo();
}
---------------------------------------------------------------------------------------------------------
//蔬菜抽象接口
public interface Vegetable {
	public void vegetableInfo();
}
---------------------------------------------------------------------------------------------------------
//具体类:北方水果
public class NorthFruit implements Fruit {
	@Override
	public void fruitInfo() {
		System.out.println("北方苹果");
	}
}
---------------------------------------------------------------------------------------------------------
public class SouthFruit implements Fruit{
	@Override
	public void fruitInfo() {
		System.out.println("南方香蕉");
	}
}
---------------------------------------------------------------------------------------------------------
//具体类:北方蔬菜
public class NorthVegetable implements Vegetable{
	@Override
	public void vegetableInfo() {
		System.out.println("北方西红柿");
	}
}
---------------------------------------------------------------------------------------------------------
//具体类:南方蔬菜
public class SouthVegetable implements Vegetable{
	@Override
	public void vegetableInfo() {
		System.out.println("南方土豆");
	}
}

下述几个工厂文件,抽象工厂类派生具体工厂类,具体工厂类创建具体蔬菜水果类

//工厂抽象接口
public interface Factory {
	Fruit createFruit();
	Vegetable createVegetable();
}
---------------------------------------------------------------------------------------------------------
//具体类:南方产品工厂
public class SouthProduuctFactory implements Factory{

	@Override
	public Fruit createFruit() {
		return new SouthFruit();
	}

	@Override
	public Vegetable createVegetable() {
		return new SouthVegetable();
	}
}
---------------------------------------------------------------------------------------------------------
public class NorthProductFactory implements Factory{
	@Override
	public Fruit createFruit() {
		return new NorthFruit();
	}
	
	@Override
	public Vegetable createVegetable() {
		return new NorthVegetable();
	}
}

代理模式

设计模式_第12张图片

静态代理

设计模式_第13张图片

public interface UserDao {
	public void delete();
}
---------------------------------------------------------------------------------------------------------
public class UserDaoImpl implements UserDao {
	@Override
	public void delete() {
		//如果想在删除数据的前面添加一些东西,删除数据的后面添加一些东西,但是由不想修改别人的代码,则使用代理类
		System.out.println("删除数据");
	}
}
---------------------------------------------------------------------------------------------------------
public class UserProxy implements UserDao {

	private UserDao dao;
	
	//通过构造方式接收代理对象
	public UserProxy(UserDao dao){
		this.dao=dao;
	}
	
	//在代理对象的前面、后面添加一些内容
	@Override
	public void delete() {
		System.out.println("开启事务");
		dao.delete();
		System.out.println("提交事务");
	}
}
---------------------------------------------------------------------------------------------------------
public class TestProxy {
	public static void main(String[] args) {
		UserDao dao = new UserDaoImpl();
		dao.delete();
		
		UserDao proxy = new UserProxy(dao);
		proxy.delete();
	}
}

动态代理

JDK代理

设计模式_第14张图片

public interface UserDao {
	public void delete();
	public void save();
}
---------------------------------------------------------------------------------------------------------
public class UserDaoImpl implements UserDao {

	@Override
	public void delete() {
		System.out.println("删除数据");
	}

	@Override
	public void save() {
		System.out.println("添加数据 ");
	}
}
---------------------------------------------------------------------------------------------------------
/*
 * JDK动态代理
 * 		jdk中生成代理对象的API
 * 			代理类所在的包:java.lang.reflect.Proxy
 * 			JDK实现代理只需要使用newProxyInstance方法,但是该方法需要接收三个数据
 * 			loader - 指定当前目标对象使用类加载器
 * 			interfaces - 目标对象实现的接口的类型,使用泛型方式确认类型
 * 			h - 事件处理,执行目标对象的方法时,会触发事件处理器的方法,会把当前执行目标对象的方法作为参数传入
 */
public class UserProxy {
	private Object object;
	
	public UserProxy(Object object){
		this.object=object;
	}
	
	public Object getProxyObject(){
		//接下来调用的是Java中的一个API
		//getClassLoader()是反射中的类加载器
		//获取类实现的一个接口object.getClass().getInterfaces()
		//事件方法,是一个接口,传入一个接口,所以需要用内部类的一种方式来实现
		return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), new InvocationHandler() {
			
			@Override/*下面参数中,动态调用哪些方法,method就是谁*/
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				System.out.println("开启事务");
				Object invoke = method.invoke(object, args);//这里是原本的内容,上下为要添加的内容
				System.out.println("提交事务");
				return invoke;
			}
		});
	}
}
---------------------------------------------------------------------------------------------------------
public class TestProxy {
	public static void main(String[] args) {
		
		UserDao dao = new UserDaoImpl();
		
		UserProxy up = new UserProxy(dao);
		
		UserDao proxyObject = (UserDao) up.getProxyObject();
		proxyObject.delete();
		proxyObject.save();
	}
}
Cglib代理

设计模式_第15张图片

引入Spring的jar包,在项目中新建一个lib文件夹,将Spring的jar包Copy进去,然后右键那个文件,再点击Build Path
再点击Add to Build Path
public class UserDao {
	public  void save() {
		System.out.println("保存数据");
	}
}
---------------------------------------------------------------------------------------------------------
/*
 * Cglib子类代理工厂
 * 对UserDao在内存中动态构件一个子类对象
 */
public class CglibProxyFactory implements MethodInterceptor{//要实现Cglib必须继承一个接口
	
	private Object target;
	
	public CglibProxyFactory(Object target){
		this.target = target;
	}
	
	//给目标对象创建一个代理
	public Object getProxyInstance(){
		//1.工具类
		Enhancer en = new Enhancer();
		//2.设置父类
		en.setSuperclass(target.getClass());
		//3.设置回调函数
		en.setCallback(this);
		//4.创建子类(代理对象)
		return en.create();
	}
	
	@Override
	public Object intercept(Object arg0,Method arg1,Object[] arg2,MethodProxy arg3) throw Throwable{
		System.out.println("开启事务");
		//执行目标对象的方法
		Object invokeObject = Method.invoke(target,arg2);
		System.out.println("提交事务");
		return null;
	}
}
---------------------------------------------------------------------------------------------------------
public class TestCglib {
	public static void main(String[] args) {
		//目标对象
		UserDao dao = newUserDao();
		//代理对象
		CglibProxyFactory c = new CglibProxyFactory(dao);
		UserDao d = (UserDao) c.getProxyInstance();
		//执行代理对象的方法
		d.save();
	}
}

你可能感兴趣的:(Java语言)