当前位置: 首页 > news >正文

设计模式简单入门(下)

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

接着上一篇文章继续

13.状态模式

定义:当一个对象的内在状态改变时允许改变其行为,这个对象看起来是改变了其类。状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况,吧状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。

框架:拥有状态的对象Context,当Context状态切换时的状态切换逻辑判断不是在Context里实现,而是在状态实例里实现。

代码:

//拥有多个状态的Context
public class Context {
	private State state;
	public Context(State state) {
		super();
		this.state = state;
	}
	public State getState() {
		return state;
	}
	public void setState(State state) {
		this.state = state;
	}
    //改变状态函数,由于状态转化逻辑在具体状态里,所以让当前状态state调用handle转换状态
	public void changeState(){
		this.state.Handle(this);
	}
}
//状态接口,包含状态状态转换抽象方法
public interface State {
	public abstract void Handle(Context context);
}
//某具体状态,实现了状态转换函数Handle,并打印了日志
public class ConcreteStateA implements State {
	@Override
	public void Handle(Context context) {
		// TODO Auto-generated method stub
		context.setState(new ConcreteStateB());
		System.out.println("状态A转换到了状态B");
	}
}
//实现状态转换过程
public class Test {
	public static void main(String[] args) {
		Context c = new Context(new ConcreteStateA());
		c.changeState();
		c.changeState();
		c.changeState();
	}
}

14.适配器模式

定义:将一个类的接口转换成客户希望的另外一个接口,适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

框架:适用于两个类所做的事情相同或相似,但是具有不同接口,且双方都不容易被修改考虑使用适配器模式。

 代码:

//目标对象发出的请求时普通的请求
public abstract class Target {
	public void request(){
		System.out.println("普通的请求");
	}
}
//适配器适配被适配对象
public class Adapter extends Target {
	Adaptee adaptee = new Adaptee();
	@Override
	public void request() {
		// TODO Auto-generated method stub
		adaptee.request();;
	}
}
//被适配对象与目标对象都是发出请求,但是请求类型不兼容
public class Adaptee {
	public void request(){
		System.out.println("特殊的请求");
	}
}

15.备忘录模式

定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原先保存的状态。

框架:Originator为主体,内保存有状态属性,并且有导入备忘录和导出备忘录的方法。备忘录保存主体特定的状态。Caretake是保存备忘录的。这样保存和恢复备忘录都不会暴露备忘录内存有的状态的细节。

 代码:

//拥有状态的主体
public class Originator {
	private String state;
	public void setState(String state) {
		this.state = state;
	}
	public void show(){
		System.out.println(state);
	}
    //导出含有状态的备忘录
	public Memento createMemento(){
		return new Memento(state);
	}
    //导入备忘录的状态
	public void setMemento(Memento memento){
		this.state = memento.getState();
	}
}
//备忘录
public class Memento {
	private String state;
	public Memento(String state) {
		super();
		this.state = state;
	}
	public String getState() {
		return state;
	}
}
//备忘录管理者
public class Caretaker {
	private Memento memento;
	public Memento getMemento() {
		return memento;
	}
	public void setMemento(Memento memento) {
		this.memento = memento;
	}
}

16.组合模式

定义:将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

框架:抽象组件包含添加和移除的组合方法、显示方法,叶子类即单个对象不会实现组合方法,组合类则会全部实现。即用户使用的时候统一使用组件类,具体是叶子类还是组合类只是具体实现不同并不影响使用选择。

 代码:

//通用组件
public abstract class Component {
	protected String name;
	public Component(String name) {
		super();
		this.name = name;
	}
	public abstract void add(Component cmp);
	public abstract void remove(Component cmp);
	public abstract void display(int depth);
}
//叶子类,即单个组件
public class Leaf extends Component {
	public Leaf(String name){
		super(name);
	}
    //叶子节点无子节点因此不实现增加和减少组件
	@Override
	public void add(Component cmp) {
		// TODO Auto-generated method stub
	}
	@Override
	public void remove(Component cmp) {
		// TODO Auto-generated method stub
	}
	@Override
	public void display(int depth) {
		// TODO Auto-generated method stub
		StringBuilder sb = new StringBuilder();
		for(int i = 0 ; i < depth ; i++) sb.append("-");
		System.out.println(sb + name);
	}
}
//组合组件,实现添加和减少子节点,并且display时实现递归调用子节点的display
public class Composite extends Component {
	public Composite(String name){
		super(name);
	}
	private List<Component> child = new ArrayList<>();
	@Override
	public void add(Component cmp) {
		// TODO Auto-generated method stub
		child.add(cmp);
	}
	@Override
	public void remove(Component cmp) {
		// TODO Auto-generated method stub
		child.remove(cmp);
	}
	@Override
	public void display(int depth) {
		// TODO Auto-generated method stub
		StringBuilder sb = new StringBuilder();
		for(int i = 0 ; i < depth ; i++){
			sb.append("-");
		}
		System.out.println(sb + name);
		for(Component tmp : child){
			tmp.display(depth + 2);
		}
	}
}

17.迭代器模式

定义:提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。

框架:例如集合类的迭代器,通过集合类创建迭代器,然后使用迭代器进行迭代操作而不需知道里面的细节。

代码:

//聚集接口包含创造迭代器的抽象方法
public interface Aggregate {
	public abstract Iterator createIterator();
}
//具体聚集类实现了聚集接口的创造迭代器的方法
public class ConcreteAggregate implements Aggregate {
	private List<String> list = new ArrayList<>();
	@Override
	public Iterator createIterator() {
		// TODO Auto-generated method stub
		return new ConcreteIterator(this);
	}
	public int getSize(){
		return list.size();
	}
	public String getItem(int index){
		return list.get(index);
	}
	public void setItem(String o){
		list.add(o);
	}
}
//迭代器接口,包含通用的迭代抽象方法
public interface Iterator {
	public abstract String First();
	public abstract String Next();
	public abstract boolean isDone();
	public abstract String currentItem();
}
//具体迭代器实现了迭代方法
public class ConcreteIterator implements Iterator {
	private ConcreteAggregate aggregate;
	private int current;
	public ConcreteIterator(ConcreteAggregate aggregate) {
		super();
		this.aggregate = aggregate;
		current = 0;
	}
	@Override
	public String First() {
		// TODO Auto-generated method stub
		return aggregate.getItem(0);
	}
	@Override
	public String Next() {
		// TODO Auto-generated method stub
		String next = null;
		current++;
		if(current + 1 <= aggregate.getSize()){
			next = aggregate.getItem(current);
		}
		return next;
	}
	@Override
	public boolean isDone() {
		// TODO Auto-generated method stub
		return (current+1) > aggregate.getSize() ? true:false;
	}
	@Override
	public String currentItem() {
		// TODO Auto-generated method stub
		return aggregate.getItem(current);
	}
}
//迭代器使用
public class Test {
	public static void main(String[] args) {
		ConcreteAggregate aggregate = new ConcreteAggregate();
		aggregate.setItem("waffle");
		aggregate.setItem("cube");
		aggregate.setItem("xyl");
		Iterator iterator = aggregate.createIterator();
		while(!iterator.isDone()){
			System.out.println(iterator.currentItem());
			iterator.Next();
		}
	}
}

18.桥接模式

定义:将抽象部分与它的实现部分分离,使它们都可以独立的变化。

框架:定义中指的抽象和实现部分不是指的通常意义上的抽象类和实现子类,而是指图中的“抽象”和“实现”部分。实际上就是原来“抽象”部分类和“实现”部分类是在同一颗继承树上的继承关系对应的抽象类和实现类,发生变化就是在子类中不断扩展进行处理。而桥接模式就是将上述情况使用组合/聚合原则将“抽象”和“实现”部分拆分,不适用继承而使换用组合/聚合桥接,发生变化时各自变化各自的,松耦合。

 代码:

//"实现"部分的抽象类
public abstract class Implementor {
	public abstract void OperationImp();
}
//"实现"部分的具体类
public class ConcreteImplementorA extends Implementor {
	@Override
	public void OperationImp() {
		// TODO Auto-generated method stub
		System.out.println("实现了A方法");
	}
}
//"抽象"部分的抽象类
public abstract class Abstraction {
    //这里持有"实现"类的引用就是利用组合/聚合的思想进行桥接
	protected Implementor implementor;
	public void setImplementor(Implementor implementor) {
		this.implementor = implementor;
	}
	public abstract void Operation();
}
//"抽象"部分的具体类
public class RefinedAbstraction extends Abstraction {
	@Override
	public void Operation() {
		// TODO Auto-generated method stub
		implementor.OperationImp();
	}
}
//实现过程
public class Test {
	public static void main(String[] args) {
		Implementor ia = new ConcreteImplementorA();
		Implementor ib = new ConcreteImplementorB();
		Abstraction a = new RefinedAbstraction();
		a.setImplementor(ia);
		a.Operation();
		a.setImplementor(ib);
		a.Operation();
	}
}

19.命令模式

定义:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。

框架:命令模式可以设计一个命令队列,在需要的情况下可以将命令记入日志,且允许接受请求的一方是否要否决请求。可以很容易的增加新的命令而不影响其他类。

//命令的最终实施者
public class Receiver {
	public void Action(){
		System.out.println("执行命令");
	}
}
//命令抽象类,包含绑定命令最终实施者的方法和执行命令的抽象方法
public abstract class Command {
	protected Receiver receiver;
	public Command(Receiver receiver) {
		super();
		this.receiver = receiver;
	}
	public abstract void Execute();
}
//具体的命令实现了执行方法,即调用实施者的实施方法
public class ConcreteCommand extends Command {
	public ConcreteCommand(Receiver receiver){
		super(receiver);
	}
	@Override
	public void Execute() {
		// TODO Auto-generated method stub
		receiver.Action();
	}
}
//调用者包含获得命令的方法和执行命令的方法
public class Invoker {
	private Command command;
	public void setCommand(Command command){
		this.command = command;
	}
	public void ExecuteCommand(){
		command.Execute();
	}
}

20.职责链模式

定义:使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,知道有一个对象处理它为止。

框架:例如异常处理就使用到了职责链模式,所有处理者按优先顺序串联成一条链,请求就沿着这条链被处理或向下传递给后面的处理者处理。

代码:

//处理者的抽象类,包含设置后续职责继承者方法和处理请求的抽象方法
public abstract class Handler {
	protected Handler successor;
	public void setSuccessor(Handler handler){
		this.successor = handler;
	}
	public abstract void handleRequset(int request);
}
//具体处理者,实现了处理请求的方法,包括若不能处理交给后续的继承者处理
public class ConcreteHandlerA extends Handler {
	@Override
	public void handleRequset(int request) {
		// TODO Auto-generated method stub
		if(request > 0 && request < 10){
			System.out.println("A处理了该请求");
		} else if(successor != null){
			successor.handleRequset(request);
		}
	}
}
//处理过程
public class Test {
	public static void main(String[] args) {
		Handler a = new ConcreteHandlerA();
		Handler b = new ConcreteHandlerB();
		a.setSuccessor(b);
		int[] requests = {1,5,10,15};
		for(int request : requests){
			a.handleRequset(request);
		}
	}
}

21.中介者模式

定义:用一个中介者对象来封装一系列的对象交互。中介者使各对象不需要显式地相互作用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

框架:中介者包含绑定要交流的对象的方法,还包含发送转送消息的方法。交流对象包含设置中介者的方法,还包含发送消息的方法,方法中调用中介者发送消息。中介者模式降低了沟通者之间的耦合,并将沟通方式的复杂性交给了中介者来负责。

 代码:

//中介者接口,包含发送消息的抽象方法
public interface Mediator {
	public abstract void Send(Person person,String message);
}
//具体中介者,实现了发送消息的方法,并且含有绑定交流双方的方法
public class ConcreteMediator implements Mediator {
	private ConcretePersonA concretePersonA;
	private ConcretePersonB concretePersonB;
	public void setConcretePersonA(ConcretePersonA concretePersonA) {
		this.concretePersonA = concretePersonA;
	}
	public void setConcretePersonB(ConcretePersonB concretePersonB) {
		this.concretePersonB = concretePersonB;
	}
	@Override
	public void Send(Person person, String message) {
		// TODO Auto-generated method stub
		if(person == concretePersonA){
			concretePersonB.Notify();
		} else if (person == concretePersonB){
			concretePersonA.Notify();
		}
	}
}
//交流对象包含绑定中介者的方法
public class Person {
	protected Mediator mediator;
	public Person(Mediator mediator) {
		super();
		this.mediator = mediator;
	}
}
//具体交流者,包含绑定中介者的方法,包含调用中介者发送消息的方法,还包含收到消息的打印日志的方法
public class ConcretePersonA extends Person {
	public ConcretePersonA(Mediator mediator){
		super(mediator);
	}
	public void Send(String message){
		mediator.Send(this, message);
	}
	public void Notify(){
		System.out.println("ConcretePersonA 收到了消息");
	}
}

22.享元模式

定义:运用共享技术有效地支持大量细粒度的对象。

框架:若需要创建大量的对象,并且这些对象大部分的信息的是相同的,则可以考虑使用享元模式,将大量的类抽象为享元,将这些享元中大部分信息相同的部分抽象为父类的抽象方法,不相同部分可以使用外部传递进来,将享元保存在享元工厂,使用的时候直接调用出来,这样减少了创建大量对象的开销。例如线程池用的就是享元模式。

代码:

//抽象享元类,将享元中相同的Operation方法抽象为抽象方法
public abstract class FlyWeight {
	public abstract void Operation(int extrinsicstate);
}
//具体的享元实现了相同的Operation方法,对于不同的信息通过extrinsicstate传入
public class SharedConcreteFlyWeight extends FlyWeight {
	@Override
	public void Operation(int extrinsicstate) {
		// TODO Auto-generated method stub
		System.out.println("SharedConcreteFlyWeight" + extrinsicstate);
	}
}
//享元工厂,将享元保存在工厂内部,需要的时候直接提取出来
public class FlyWeightFactory {
	private HashMap<String,FlyWeight> map = new HashMap<>(); 
	public FlyWeightFactory(){
		map.put("X", new SharedConcreteFlyWeight());
		map.put("Y", new SharedConcreteFlyWeight());
		map.put("Z", new SharedConcreteFlyWeight());
	}
	public FlyWeight getFlyWeight(String key){
		return map.get(key);
	}
}
//享元可以不共享,这样就不必放在享元工厂里。
public class UnSharedConcreteFlyWeight extends FlyWeight {
	@Override
	public void Operation(int extrinsicstate) {
		// TODO Auto-generated method stub
		System.out.println("UnSharedConcreteFlyWeight" + extrinsicstate);
	}
}
//享元模式具体实现
public class Test {
	public static void main(String[] args) {
		int extrinsicstate = 22;
		FlyWeightFactory factory = new FlyWeightFactory();
		factory.getFlyWeight("X").Operation(--extrinsicstate);
		factory.getFlyWeight("Y").Operation(--extrinsicstate);
		factory.getFlyWeight("Y").Operation(--extrinsicstate);
		UnSharedConcreteFlyWeight uf = new UnSharedConcreteFlyWeight();
		uf.Operation(--extrinsicstate);
	}
}

23.解释器模式

定义:给定一个语言,定义它的文字的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

框架:即对一段内容进行解释,每扫描固定一小段,判断该小段的类型然后用特定的解释器去解释,这样需要新增或改变解释的方式只需要增加并换用新的解释器即可。例如程序的解释器的实现。

代码:

//抽象的解释器,定义了抽象的解释方法
public abstract class AbstractExpression {
	public abstract void Iterpret(Context context);
}
//具体的解释器,实现了具体解释的方法,当调用此解释器是传入内容执行解释方法
public class TerminalExpression extends AbstractExpression {
	@Override
	public void Iterpret(Context context) {
		// TODO Auto-generated method stub
		System.out.println("非终结符表达式");
	}
}
//要解释的内容
public class Context {
	private String input,output;
	public String getInput() {
		return input;
	}
	public void setInput(String input) {
		this.input = input;
	}
	public String getOutput() {
		return output;
	}
	public void setOutput(String output) {
		this.output = output;
	}
}
//解释过程
public class Test {
	public static void main(String[] args) {
		Context context = new Context();
		List<AbstractExpression> list = new ArrayList<>();
		list.add(new NonTerminalExpression());
		list.add(new NonTerminalExpression());
		list.add(new TerminalExpression());
		for(AbstractExpression expression : list){
            //应该是根据内容的不同判断使用何种解释器去解释,这里是直接用固定顺序使用解释器了
			expression.Iterpret(context);
		}
	}
}

24.访问者模式

定义:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

框架:旨在把数据结构与数据结构上的操作分离,即对数据结构的操作不会影响数据结构,需要的添加新的操作只要添加新的访问者即可,数据结构对应着ObjectStructure,数据对应Element,访问者对应不同的ConcreteVisitor。适用于数据结构较稳定,操作不稳定的情况。

代码:

//抽象元素类,包含接受访问者的抽象方法
public abstract class Element {
	public abstract void Accept(Visitor visitor);
}
//具体元素,实现了接受访问者的方法,即直接调用访问者的访问该元素的方法
public class ConcreteElementA extends Element {
	@Override
	public void Accept(Visitor visitor) {
		// TODO Auto-generated method stub
		visitor.visitConcreteElementA(this);;
	}
}
//元素结构体,保存已有的元素列表,提供增减元素的方法和接受访问的者访问的方法,访问者访问时调用所有的元素接受访问。
public class ObjectStructure {
	private List<Element> list = new ArrayList<>();
	public void addElement(Element e){
		list.add(e);
	}
	public void removeElement(Element e){
		list.remove(e);
	}
	public void Accept(Visitor visitor){
		for(Element e : list){
			e.Accept(visitor);
		}
	}
}
//访问者抽象类,包含访问各个元素的抽象方法
public abstract class Visitor {
	public abstract void visitConcreteElementA(ConcreteElementA ea);
	public abstract void visitConcreteElementB(ConcreteElementB eb);
}
//具体的访问者,实现了访问各个元素的方法,并打印访问日志
public class ConcreteVisitorA extends Visitor {
	@Override
	public void visitConcreteElementA(ConcreteElementA ea) {
		// TODO Auto-generated method stub
		System.out.println("ConcreteVisitorA访问了" + ea.toString());
	}
	@Override
	public void visitConcreteElementB(ConcreteElementB eb) {
		// TODO Auto-generated method stub
		System.out.println("ConcreteVisitorA访问了" + eb.toString());
	}
}
//访问者模式实现过程
public class Test {
	public static void main(String[] args) {
		Element ea = new ConcreteElementA();
		Element eb = new ConcreteElementB();
		ObjectStructure os = new ObjectStructure();
		os.addElement(ea);
		os.addElement(eb);
		Visitor va = new ConcreteVisitorA();
		Visitor vb = new ConcreteVisitorB();
		os.Accept(va);
		os.Accept(vb);
	}
}

 

转载于:https://my.oschina.net/waffle930/blog/754862

相关文章:

  • Linux下完全删除Oracle
  • mysql外键实战
  • php 使用pathinfo(), parse_url(), basename()解析URL
  • gitlab 统计
  • 做软件开发的同学常用软件列表
  • 用Java编写你自己的简单HTTP服务器
  • Python终端如何输出彩色字体
  • “10%时间”:优点和缺点——敏捷海滩会议上Elizabeth Pope的报告
  • linux top命令VIRT,RES,SHR,DATA的含义
  • python-----Queue模块
  • Linux查找
  • SDN组网相关解决方案
  • java面试每日一题13
  • Maven系列--maven-compiler-plugin的使用
  • C# 把一个文件夹下所有文件复制到另一个文件夹下
  • [笔记] php常见简单功能及函数
  • echarts花样作死的坑
  • fetch 从初识到应用
  • HTTP请求重发
  • Intervention/image 图片处理扩展包的安装和使用
  • JAVA_NIO系列——Channel和Buffer详解
  • JavaScript设计模式与开发实践系列之策略模式
  • linux学习笔记
  • Median of Two Sorted Arrays
  • PAT A1120
  • vue+element后台管理系统,从后端获取路由表,并正常渲染
  • Webpack 4 学习01(基础配置)
  • 从@property说起(二)当我们写下@property (nonatomic, weak) id obj时,我们究竟写了什么...
  • 检测对象或数组
  • 前端每日实战 2018 年 7 月份项目汇总(共 29 个项目)
  • 让你成为前端,后端或全栈开发程序员的进阶指南,一门学到老的技术
  • 日剧·日综资源集合(建议收藏)
  • 如何在GitHub上创建个人博客
  • 入手阿里云新服务器的部署NODE
  • 学习笔记:对象,原型和继承(1)
  • 树莓派用上kodexplorer也能玩成私有网盘
  • #NOIP 2014# day.2 T2 寻找道路
  • $.ajax()方法详解
  • (145)光线追踪距离场柔和阴影
  • (day 2)JavaScript学习笔记(基础之变量、常量和注释)
  • (html5)在移动端input输入搜索项后 输入法下面为什么不想百度那样出现前往? 而我的出现的是换行...
  • (翻译)Entity Framework技巧系列之七 - Tip 26 – 28
  • (欧拉)openEuler系统添加网卡文件配置流程、(欧拉)openEuler系统手动配置ipv6地址流程、(欧拉)openEuler系统网络管理说明
  • .net core Swagger 过滤部分Api
  • .NET CORE使用Redis分布式锁续命(续期)问题
  • .Net Remoting常用部署结构
  • .net 验证控件和javaScript的冲突问题
  • .NET实现之(自动更新)
  • .NET中的十进制浮点类型,徐汇区网站设计
  • /etc/apt/sources.list 和 /etc/apt/sources.list.d
  • @SentinelResource详解
  • []Telit UC864E 拨号上网
  • [C#]DataTable常用操作总结【转】
  • [HTML]Web前端开发技术18(HTML5、CSS3、JavaScript )HTML5 基础与CSS3 应用——喵喵画网页
  • [iOS]iOS获取设备信息经常用法