设计模式之策略模式&原型模式&观察模式&装饰模式

1. 原型模式

1.1 什么是原型模式

克隆
原型模式是一个创建型的模式。原型二字表明了改模式应该有一个样板实例,用户从这个样板对象中复制一个内部属性一致的对象,这个过程也就是我们称的“克隆”。被复制的实例就是我们所称的“原型”,这个原型是可定制的。原型模式多用于创建复杂的或者构造耗时的实例,因为这种情况下,复制一个已经存在的实例可使程序运行更高效。

1.2 原型模式应用场景

(1) 类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等,通过原型拷贝避免这些消耗。
(2)通过new产生的一个对象需要非常繁琐的数据准备或者权限,这时可以使用原型模式。
(3)一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用,即保护性拷贝。
(4)Spring框架中的多例就是使用原型。

1.3 原型模式UML类图(通用)

原型模式主要用于对象的复制,它的核心是就是类图中的原型类Prototype。Prototype类需要具备以下两个条件:
  (1)实现Cloneable接口。在java语言有一个Cloneable接口,它的作用只有一个,就是在运行时通知虚拟机可以安全地在实现了此接口的类上使用clone方法。在java虚拟机中,只有实现了这个接口的类才可以被拷贝,否则在运行时会抛出CloneNotSupportedException异常。
  (2)重写Object类中的clone方法。Java中,所有类的父类都是Object类,Object类中有一个clone方法,作用是返回对象的一个拷贝,但是其作用域protected类型的,一般的类无法调用,因此Prototype类需要将clone方法的作用域修改为public类型。

1.4 原型模式分类

原型模式分为浅复制和深复制

浅复制 —-只是拷贝了基本类型的数据,而引用类型数据,复制后也是会发生引用,我们把这种拷贝叫做“(浅复制)浅拷贝”,换句话说,浅复制仅仅是指向被复制的内存地址,如果原地址中对象被改变了,那么浅复制出来的对象也会相应改变。

深复制 —-在计算机中开辟了一块新的内存地址用于存放复制的对象。

1.5 演示实例

/*
 * 书本类型,扮演的是ConcretePrototype角色,而Cloneable扮演Prototype角色
 */
public class Book implements Cloneable {

	private String title;// 标题
	private ArrayList<String> image = new ArrayList<String>();// 图片名列表

	public Book() {
		super();
	}

	/**
	 * 重写拷贝方法
	 */
	@Override
	protected Book clone() {
		try {
			Book book = (Book) super.clone();//
			book.image=(ArrayList<String>)this.image.clone();//深复制
			return book;
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return null;
	}

	public ArrayList<String> getImage() {
		return image;
	}

	public void addImage(String img) {
		this.image.add(img);
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	/**
	 * 打印内容
	 */
	public void showBook() {
		System.out.println("----------------------Start----------------------");

		System.out.println("title:" + title);
		for (String img : image) {
			System.out.println("image name:" + img);
		}

		System.out.println("----------------------End----------------------");
	}
}

客户端代码

public class Client02 {

	public static void main(String[] args) {
		Book book1 = new Book();
		book1.setTitle("书1");
		book1.addImage("图1");
		book1.showBook();
		//以原型方式拷貝一份
		Book book2 = book1.clone();
		book2.showBook();
		book2.setTitle("书2");
		book2.addImage("圖2");
		book2.showBook();
		//再次还原打印书本
		book1.showBook();
	}

}

2. 装饰模式

2.1 什么是装饰模式

装饰器模式,也成为包装模式,顾名思义,就是对已经存在的某些类进行装饰,以此来扩展一些功能。其结构图如下:
在这里插入图片描述
Component为统一接口,也是装饰类和被装饰类的基本类型。
ConcreteComponent为具体实现类,也是被装饰类,他本身是个具有一些功能的完整的类。
Decorator是装饰类,实现了Component接口的同时还在内部维护了一个ConcreteComponent的实例,并可以通过构造函数初始化。而Decorator本身,通常采用默认实现,他的存在仅仅是一个声明:我要生产出一些用于装饰的子类了。而其子类才是赋有具体装饰效果的装饰产品类。
ConcreteDecorator是具体的装饰产品类,每一种装饰产品都具有特定的装饰效果。可以通过构造器声明装饰哪种类型的ConcreteComponent,从而对其进行装饰。

2.2 装饰模式案例

//房屋基础接口
public interface House {
	 void run();
}
public class HouseImpl implements House {
    @Override
    public void run() {
        System.out.println("我的房屋");
    }
}
//房屋装饰类
public class HouseDecorate implements House {
   private House house;
   public HouseDecorate(House house){
	  this.house=house;
   }
	@Override
	public void run() {
		house.run();
	}

}
public class HouseDecorateImpl extends HouseDecorate {

	public HouseDecorateImpl(House house) {
		super(house);
	}

	@Override
	public void run() {
		super.run();
		System.out.println("贴上墙纸..");
	}

}

客户端调用

public class ClientTest {

	public static void main(String[] args) {
		HouseImpl houseImpl = new HouseImpl();
		houseImpl.run();
		System.out.println("###新增贴上墙纸..###");
		HouseDecorate houseDecorate = new HouseDecorateImpl(houseImpl);
		houseDecorate.run();
	}

}

2.3 装饰与代理区别

装饰器模式关注于在一个对象上动态的添加方法,然而代理模式关注于控制对对象的访问。换句话 说,用代理模式,代理类(proxy class)可以对它的客户隐藏一个对象的具体信息。因此,当使用代理模式的时候,我们常常在一个代理类中创建一个对象的实例。并且,当我们使用装饰器模 式的时候,我们通常的做法是将原始对象作为一个参数传给装饰者的构造器。

2.4 装饰模式应用场景

在IO中,具体构件角色是节点流,装饰角色是过滤流。
FilterInputStream和FilterOutputStream是装饰角色,而其他派生自它们的类则是具体装饰角色。
DataoutputStream out=new DataoutputStream(new FileoutputStream());
这就是 装饰者模式,DataoutputStream是装饰者子类,FileoutputStream是实现接口的子类。
这里不会调用到装饰者类–FilteroutputStream,只是作为继承的另一种方案,对客户端来说是透明的,是为了功能的扩张.

3. 策略模式

3.1 什么是策略模式

定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。

3.2 策略模式由三种角色组成

3.3 策略模式应用场景

策略模式的用意是针对一组算法或逻辑,将每一个算法或逻辑封装到具有共同接口的独立的类中,从而使得它们之间可以相互替换。策略模式使得算法或逻辑可以在不影响到客户端的情况下发生变化。说到策略模式就不得不提及OCP(Open Closed Principle) 开闭原则,即对扩展开放,对修改关闭。策略模式的出现很好地诠释了开闭原则,有效地减少了分支语句。

3.4 策略模式代码

此代码通过模拟不同会员购物车打折力度不同分为三种策略,初级会员,中级会员,高级会员。

//策略模式 定义抽象方法 所有支持公共接口
abstract class Strategy {
	// 算法方法
	abstract void algorithmInterface();
}
class StrategyA extends Strategy {

	@Override
	void algorithmInterface() {
		System.out.println("算法A");
	}

}
class StrategyB extends Strategy {

	@Override
	void algorithmInterface() {
		System.out.println("算法B");

	}

}
class StrategyC extends Strategy {
	@Override
	void algorithmInterface() {
		System.out.println("算法C");
	}
}
// 使用上下文维护算法策略
class Context {
	Strategy strategy;
	public Context(Strategy strategy) {
		this.strategy = strategy;
	}
	public void algorithmInterface() {
		strategy.algorithmInterface();
	}
}
class ClientTestStrategy {
	public static void main(String[] args) {
		Context context;
		context = new Context(new StrategyA());
		context.algorithmInterface();
		context = new Context(new StrategyB());
		context.algorithmInterface();
		context = new Context(new StrategyC());
		context.algorithmInterface();
	}
}

4. 观察者模式

4.1 什么是观察者模式

观察者模式(Observer),是一种行为性模型,行为型模式关注的是系统中对象之间的相互交互,解决系统在运行时对象之间的相互通信和协作,进一步明确对象的职责。相比来说,创建型模式关注对象的创建过程,结构型模式关注对象和类的组合关系。

4.2 模式的职责

观察者模式主要用于1对N的通知。当一个对象的状态变化时,他需要及时告知一系列对象,令他们做出相应。
实现有两种方式:
推:每次都会把通知以广播的方式发送给所有观察者,所有的观察者只能被动接收。
拉:观察者只要知道有情况即可,至于什么时候获取内容,获取什么内容,都可以自主决定。

4.3 模式的实现

/**
 * @Auther: 洺润Star
 * @Date: 2020/3/6 10:46
 * @Description:观察者的接口,用来存放观察者共有方法
 */
public interface Observer {
    // 观察者方法
    void update(RealObserver realObserver);
}
/**
 * @Auther: 洺润Star
 * @Date: 2020/3/6 10:47
 * @Description:观察对象的父类
 */
public class Subjecct {
    //观察者的存储集合
    private List<Observer> list = new ArrayList<>();

    // 注册观察者方法
    public void registerObserver(Observer obs) {
        list.add(obs);
    }
    // 删除观察者方法
    public void removeObserver(Observer observer,RealObserver realObserver) {
        list.remove(observer);
        this.notifyAllObserver(realObserver);
    }

    // 通知所有的观察者更新
    public void notifyAllObserver(RealObserver realObserver) {
        for (Observer observer : list) {
            observer.update(realObserver);
        }
    }

}
/**
 * @Auther: 洺润Star
 * @Date: 2020/3/6 10:48
 * @Description:具体观察者对象的实现
 */
public class RealObserver extends Subjecct {
    //被观察对象的属性
    private int state;
    public int getState(){
        return state;
    }
    public void  setState(int state){
        this.state=state;
        //主题对象(目标对象)值发生改变
        this.notifyAllObserver(this);
    }

}
/**
 * @Auther: 洺润Star
 * @Date: 2020/3/6 10:50
 * @Description:观察者
 */
public class ObserverA implements Observer {
    private int state;
    @Override
    public void update(RealObserver realObserver) {
        this.state= realObserver.getState();
    }

    public int getMyState(){
        return state;
    }
}

public class Client {

 public static void main(String[] args) {
        // 目标对象
        RealObserver subject = new RealObserver();
        // 创建多个观察者
        ObserverA obs1 = new ObserverA();
        ObserverA obs2 = new ObserverA();
        ObserverA obs3 = new ObserverA();
        // 注册到观察队列中
        subject.registerObserver(obs1);
        subject.registerObserver(obs2);
        subject.registerObserver(obs3);
        // 改变State状态
        subject.setState(300);
        System.out.println(obs1.getMyState());
        System.out.println(obs2.getMyState());
        System.out.println(obs3.getMyState());
        // 改变State状态
        subject.setState(400);
        System.out.println(obs1.getMyState());
        System.out.println(obs2.getMyState());
        System.out.println(obs3.getMyState());
        //删除观察者
        subject.removeObserver(obs1,subject);
        System.out.println("删除一个观察者");
        // 改变State状态
        subject.setState(500);
        System.out.println(obs1.getMyState());//值将不会再变化
        System.out.println(obs2.getMyState());
        System.out.println(obs3.getMyState());
    }
}

4.4 观察者模式应用场景

关联行为场景,需要注意的是,关联行为是可拆分的,而不是“组合”关系。
事件多级触发场景。
跨系统的消息交换场景,如消息队列、事件总线的处理机制。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值