设计模式笔记
2016-04-18 18:49
381 查看
1、简单工厂
简单工厂就是将一些具有相同操作,提取出其共有方法,然后让这些类继承或实现这些方法的接口。最后用一个工厂类,利用其静态函数针对外部不同操作,生成不同类的实例,并返回其父对象。以后添加操作,只要添加一个新的操作类就可以了。
Operation抽象类,抽象方法为getResult
package com.main; public abstract class Operation { void getResult(){ } }<span style="font-family:Arial, Helvetica, sans-serif;"><span style="white-space: normal;"> </span></span>OperationAdd类,加操作
package com.main; public class OperationAdd extends Operation{ @Override void getResult() { // TODO Auto-generated method stub System.out.print("this add operation\n"); } }OperationMul类,乘操作
package com.main; public class OperationMul extends Operation{ @Override void getResult() { // TODO Auto-generated method stub System.out.print("this mul operation\n"); } }简单工厂类OperationFactory,静态方法根据情况返回父对象。
package com.main; public class OperationFactory { public static Operation createOperation(String operString) { // TODO Auto-generated constructor stub Operation oper=null; if(operString.equals("+")){ oper=new OperationAdd(); }else if(operString.equals("*")){ oper=new OperationMul(); } return oper; } }
思想:
(1)针对不同操作,但是具有相同方法的类。将相同方法抽象出来。
(2)在工厂中根据不同情况返回父对象即可。
2、策略模式
其实在第一章的简单工厂例子中就用到了策略模式,在这里,唯一的一点区别是,利用context上下文类,制作封装方法,并调用。抽象类Strategy
package com.main; abstract class Strategy { abstract void AlgorithmInterface(); }算法类StrategyA
package com.main; public class StrategyA extends Strategy{ @Override void AlgorithmInterface() { // TODO Auto-generated method stub System.out.print("this is StrategyA"); } }算法类StrategyB
package com.main; public class StrategyB extends Strategy{ @Override void AlgorithmInterface() { // TODO Auto-generated method stub System.out.print("this is StrategyB"); } }客户端代码:
package com.main; import java.io.Console; public class Main { public static void main(String[] args) { Context context=new Context(new StrategyA()); context.getResult(); context=new Context(new StrategyB()); context.getResult(); } }思想:
(1)对于Context的构造函数,可以利用简单工厂进行封装,只需要输入参数,自己生成Strategy,而不是传入Strategy对象。
3、单一职责原则
一个类应该具有单一职责,软件设计的许多类容,就是发现职责,并将这些职责相互分离。文中以俄罗斯方块为例,将游戏逻辑和界面分离,使得只要修改界面代码就能够在不同设备上使用。逻辑思想也比较精简:利用数组判断边界,消行。4、开放-封闭原则
开放封闭原则,软件实体如类等,可以扩展,但是不能修改。也就是可以添加类,但是不能修改类。这样在需求不断变化时,系统却可以保持稳定,而不用所有的都推倒重来。
面对变化,应该构造抽象隔离那些变化。
面对需求,对程序的改动是增加新代码进行的,而不是更改现有的代码。
5、依赖倒转原则
依赖倒转原则,抽象不应该依赖细节,细节应依赖抽象。针对接口编程,不要针对实现编程。文中以接口为例,不同公司的产品都要依赖统一接口进行。
里式代换原则,子类必须能够替换掉它们的父类型,这是显然的,因为子类继承了父类的功能。这一个原则,让使用父类类型的模块在无需修改的情况下就能扩展。
如简单工厂的第一个例子,都是操作父对象实现不同功能。
6、装饰模式
思想:(1)动态的给一个对象增加一些职责,不断叠加的模式,就和穿衣服一样。
(2)装饰方法Operation是抽象的,ConcreteDecoratorA具体类的方法中,必须先实现上一个装饰者的装饰,接着在实现自己特有的装饰
(3)这样用一个父类Decorator的方法来实现上一个装饰者的方法。并通过setComponent来接收上一个装饰者。
(4)同时被装饰对象ConcreteComponent同样应该实现自己原有的装饰方法。
(5)装饰方法放在抽象类Component中,作为父类。
Component类
package com.main; abstract class Component { abstract void Operation(); }ConcreteComponent类
package com.main; public class ConcreteComponent extends Component{ @Override void Operation() { // TODO Auto-generated method stub System.out.print("this is origin decorator\n"); } }Decorator类
package com.main; public class Decorator extends Component{ private Component component; public void setComponent(Component component){ this.component=component; } @Override void Operation() { // TODO Auto-generated method stub if(component!=null){ component.Operation(); } } }ConcreteDecoratorA类
package com.main; public class ConcreteDecoratorA extends Decorator{ @Override void Operation() { // TODO Auto-generated method stub super.Operation(); System.out.print("this decorator A\n"); } }客户端代码:
package com.main; import java.io.Console; public class Main { public static void main(String[] args) { ConcreteComponent original=new ConcreteComponent(); ConcreteDecoratorA contedetorA=new ConcreteDecoratorA(); ConcreteDecoratorB contedetorB=new ConcreteDecoratorB(); contedetorA.setComponent(original); contedetorB.setComponent(contedetorA); contedetorB.Operation(); } }输出:
this is origin decorator
this decorator A
this decorator B
7、代理模式
代理就是通过对代理的操作,来访问真实对象。思想:
(1)让真实类RealSubject和代理类Proxy都来继承抽象类Subject,并实现相同的方法。
(2)在代理类中将真实类实例的访问封装到抽象方法中。
Subject类
package com.main; abstract class Subject { abstract void Request(); }RealSubject类
package com.main; public class RealSubject extends Subject { @Override void Request() { // TODO Auto-generated method stub System.out.print("this is realSubject"); } }Proxy类
package com.main; public class Proxy extends Subject { private RealSubject realSubject; @Override void Request() { // TODO Auto-generated method stub if(realSubject==null){ realSubject=new RealSubject(); } realSubject.Request(); } }客户端代码:
package com.main; import java.io.Console; public class Main { public static void main(String[] args) { Proxy proxy=new Proxy(); proxy.Request(); } }输出:
this is realSubject
8、工厂方法模式
和简单工厂相比,简单工厂用OperationFactory的静态方法createOperate生产各种操作对象,而对于工厂方法而言,则进行了更高层次的抽象。抽象出接口createOperation,并让各种工厂实现它,以生产不同的操作对象。
但这样做,将判断操作交给 了客户端,以判断用什么工厂来生产不同操作对象。
抽象接口 IFactory
package com.main; abstract interface IFactory { abstract Operation CreateOperation(); }AddFactory类
package com.main; public class AddFactory implements IFactory { @Override public Operation CreateOperation() { // TODO Auto-generated method stub Operation oper=new OperationAdd(); return oper; } }MulFactory类
package com.main; public class MulFactory implements IFactory { @Override public Operation CreateOperation() { // TODO Auto-generated method stub Operation oper=new OperationMul(); return oper; } }
//客户端代码
package com.main; import java.io.Console; public class Main { public static void main(String[] args) { AddFactory addFactory=new AddFactory(); Operation oper=addFactory.CreateOperation(); oper.getResult(); } }输出:
this is add operation
9、原型模式
以一个为原型,进行复制后,只要修改其中某个内容就可以使用,这里的复制用深复制,也就是说必须实现Cloneable接口。工作经验类WorkExprience:
package com.main; public class WorkExprience implements Cloneable { String time; String company; @Override protected Object clone() throws CloneNotSupportedException { // TODO Auto-generated method stub WorkExprience workExprience=new WorkExprience(); return workExprience; } }简历类Resume
package com.main; public class Resume implements Cloneable{ String name; WorkExprience workExprience=new WorkExprience(); public Resume() { // TODO Auto-generated constructor stub } public void setName(String name){ this.name=name; } public void setWorkExprience(String time,String company){ workExprience.time=time; workExprience.company=company; } public Resume(WorkExprience workExp) throws CloneNotSupportedException { // TODO Auto-generated constructor stub workExprience=(WorkExprience)workExp.clone(); } @Override protected Object clone() throws CloneNotSupportedException { // TODO Auto-generated method stub Resume object=new Resume(this.workExprience); object.name=this.name; return object; } }
客户端程序:
package com.main; import java.io.Console; public class Main { public static void main(String[] args) { try { Resume resume1=new Resume(); resume1.name="hzh"; resume1.setWorkExprience("2013", "company1"); Resume resume2 = (Resume)resume1.clone(); resume2.setWorkExprience("2014", "company2"); System.out.print(resume1.workExprience.time); System.out.print(resume2.workExprience.time); } catch (CloneNotSupportedException e) { // // TODO Auto-generated catch block // e.printStackTrace(); } // } }输出20132014
思想如下:
(1)目标。对一个对象原型克隆,得到另外一个对象。
(2)如果是浅复制,直接实现clone接口即可。
(3)如果是深复制,则如上所述。需要利用构造函数,实现对子对象的复制。
10、模板方法模式
模板方法模式是代码复用的一个好方法,对于一些代码,流程一样,但是子类的实现细节一样,因此只要对子类重新实现,就可以实现原来模板代码的复用。思想:
(1)
AbstractClass类,包含抽象方法,以及模板方法。
package com.main; abstract class AbstractClass { abstract void Operation1(); abstract void Operation2(); public void TemplateMethod(){ Operation1(); Operation2(); } }ConcreteClassA类,实现特定的方法
package com.main; public class ConcreteClassA extends AbstractClass{ @Override void Operation1() { // TODO Auto-generated method stub System.out.print("this is Operation1 by A\n"); } @Override void Operation2() { // TODO Auto-generated method stub System.out.print("this is Operation2 by A\n"); } }客户端代码:最巧妙的一点就是用抽象类作为父对象,并利用子类来实例化。
package com.main; import java.io.Console; public class Main { public static void main(String[] args) { //抽象类虽然无法实例化,但是可以作为父对象使用,利用子类来实例化。 AbstractClass absTemp=new ConcreteClassA(); absTemp.TemplateMethod(); } }输出:
this is Operation1 by A
this is Operation2 by A
12、外观模式
为子系统中的一组接口提供一个一致的界面,也就是将子系统中的各种调用方法组合在一个方法中,供界面程序调用。SubSystemA类,子系统A
package com.main; public class SubSystemA { void methodA(){ System.out.print("this methodA\n"); } }
SubSystemB类,子系统B
package com.main; public class SubSystemB { void methodB(){ System.out.print("this methodB\n"); } }
Facade类,外观类,对子系统进行封装
package com.main; public class Facade { SubSystemA subA; SubSystemB subB; public Facade() { // TODO Auto-generated constructor stub subA=new SubSystemA(); subB=new SubSystemB(); } public void method(){ subA.methodA(); subB.methodB(); } }客户端代码:
package com.main; import java.io.Console; public class Main { public static void main(String[] args) { Facade facade=new Facade(); facade.method(); } }
输出:
this methodA this methodB
13、建造者模式
它主要是用于创建一些复杂的对象,这些对象内部构建间的建造顺序通常是稳定的,但是对象内部的构建面临复杂变化。如果使用了建造者模式,那么用户只需指定需要建造的类型就可以得到他们,而具体建造的过程和细节就不需知道了。若需要改变一个产品的内部表示,
只需要再定义一个具体的建造者就可以了。
Product类,为要构造的产品,由各部分组成,这些部分将由各实际Builder构造。并将由Director指挥构造。
package com.main; import java.util.ArrayList; import java.util.List; public class Product { List<String> parts=new ArrayList<String>(); public void add(String part){ parts.add(part); } public void show(){ for (String part : parts) { System.out.print(part+"\n"); } } }Builder抽象类
package com.main; abstract class Builder { abstract void BuildPartA(); abstract void BuildPartB(); abstract Product getResult(); }ConcreteBuilder1实际构造者类
package com.main; public class ConcreteBuilder1 extends Builder{ private Product product=new Product(); @Override void BuildPartA() { // TODO Auto-generated method stub product.add("builder1 and partA"); } @Override void BuildPartB() { // TODO Auto-generated method stub product.add("builder1 and partB"); } @Override Product getResult() { // TODO Auto-generated method stub return product; } }Director类
package com.main; public class Director { public void concrete(Builder builder){ builder.BuildPartA(); builder.BuildPartB(); } }
客户端代码:
package com.main; import java.io.Console; public class Main { public static void main(String[] args) { Director director=new Director(); ConcreteBuilder1 builder1=new ConcreteBuilder1(); //将各部分添加到product中 director.concrete(builder1); Product product=builder1.getResult(); product.show(); } }
输出:
builder1 and partA
builder1 and partB
思想:
(1)建造顺序由Director指挥,并将各部件添加到product中
(2)通过getResult函数返回product。
14、观察者模式
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有对象,使他们能够自动更新自己。思想:
(1)Subect抽象主题,可以在其notifyObserver函数中,调用观察者的更新函数。
(2)ConcreteSuject为抽象主题Subject的主题通知者。可以有多个。通过继承抽象主题,可以添加删除观察者。
(3)ConcreteObserver为具体观察者,可以有多个。通过对具体主题通知者的引用,可以获取主题状态,实现update函数。
(4)Observer,观察者抽象类,抽象接口update
Subect抽象主题
<span style="font-size:12px;font-weight: normal;">package com.main; import java.util.ArrayList; import java.util.List; abstract class Subject { private List<Observer> observers=new ArrayList<Observer>(); public void add(Observer observer){ observers.add(observer); } public void remove(Observer observer){ observers.remove(observer); } public void notifyObserver(){ for (Observer observer : observers) { observer.update(); } } } </span>ConcreteSuject主题通知者
<span style="font-size:12px;font-weight: normal;">package com.main; public class ConcreteSubject extends Subject{ public String subjectState; } </span>ConcreteObserver 具体观察者
<span style="font-size:12px;font-weight: normal;">package com.main; public class ConcreteObserver extends Observer{ private String observerName; private ConcreteSubject concreteSubject; @Override void update() { // TODO Auto-generated method stub System.out.print("i am Observer "+concreteSubject.subjectState); } public ConcreteObserver(ConcreteSubject concreteSubject, String observerName) { this.concreteSubject=concreteSubject; this.observerName=observerName; // TODO Auto-generated constructor stub } } </span>
Observer观察者抽象类
<span style="font-size:12px;font-weight: normal;">package com.main; abstract class Observer { abstract void update(); } </span>客户端代码:
<span style="font-size:12px;font-weight: normal;">package com.main; import java.io.Console; public class Main { public static void main(String[] args) { ConcreteSubject s=new ConcreteSubject(); //这一句是精华,让observer1绑定s,让s作为其内部引用, //可以获取s状态,同时s又添加了observer1,可以通知它 s.add(new ConcreteObserver(s,"observer1")); s.subjectState="i am subject plese update"; s.notifyObserver(); } } </span>输出:
i am Observer i am subject plese update
在设计模式一书中讲到委托,但是在java中没有这一个功能。但在C#中有
委托:
一个委托可以搭载多个方法,所有方法被依次唤起,可以使得所搭载的方法不需要属于同一个类。
相当于将观察者添加进通知者中,不知道如何解除委托。
其主要代码语句为:
public event EventHandler update;
对象.update+=new EventHandler(要添加对象的方法)
但是update方法和要添加对象方法,参数类型等必须一致。
15、抽象工厂模式
见文章:http://blog.csdn.net/liruikqn/article/details/12888511 这里转载过来抽象工厂模式(Abstract Factory Pattern)是工厂方法模式的进一步抽象,其英文原话"Provide an interface for creating families of related or dependent objects without specifying their concrete classes",翻译,“为创建一组相关或相互依赖的对象提供一个借口,无需指定它们的具体类”。抽象工厂模式通常是用于创一族产品,并且这族产品分不同的等级;不同的具体工厂类生产不同等级的一族产品。抽象工厂模式也有四种角色:抽象工厂、具体工厂、抽象产品和具体产品,具体解释参见“Java
工厂方法模式”一文。抽象工厂模式的类图如下:
可以看到产品族包括ProductA和ProductB两种产品,每个具体工厂都能生产这两种产品,只是ConcreteFactory1生产的等级为1的族产品;ConcreteFactory2生产的是等级为2的族产品。下面以上图为模型,写一个demo,测试抽象工厂模式。
[b]抽象工厂:AbstractFactory接口
[html] view
plain copy
//抽象工厂,定义了生产族产品的方法;
public interface AbstractFactory {
public ProductA factoryA();
public ProductB factoryB();
}
抽象产品:ProductA接口
[html] view
plain copy
//抽象产品A定义了产品的公共方法,产品A和B属于一个产品族
public interface ProductA {
public void method1();
public void method2();
}
抽象产品:ProductB接口
[html] view
plain copy
//抽象产品B定义了产品的公共方法,产品A和B属于一个产品族
public interface ProductB {
public void method1();
public void method2();
}
具体工厂(生产等级为2的族产品):ConcreteFactory1类
[html] view
plain copy
//ConcreateFactory1是用来生产等级为1的产品A,B;
public class ConcreateFactory1 implements AbstractFactory {
//生产等级为1的产品A
@Override
public ProductA factoryA() {
// TODO Auto-generated method stub
return new ConcreateProductA1();
}
//生产等级为1的产品B
@Override
public ProductB factoryB() {
// TODO Auto-generated method stub
return new ConcreateProductB1();
}
}
具体工厂(生产等级为1的族产品):ConcreteFactory2类
[html] view
plain copy
public class ConcreateFactory2 implements AbstractFactory {
//生产等级为2的产品A
@Override
public ProductA factoryA() {
// TODO Auto-generated method stub
return new ConcreateProductA2();
}
//生产等级为2的产品B
@Override
public ProductB factoryB() {
// TODO Auto-generated method stub
return new ConcreateProductB2();
}
}
具体产品(等级为1的A产品):ConcreteProductA1类
[html] view
plain copy
//等级为1的具体产品A
public class ConcreateProductA1 implements ProductA {
@Override
public void method1() {
// TODO Auto-generated method stub
System.out.println("等级为1的产品A的method1()");
}
@Override
public void method2() {
// TODO Auto-generated method stub
System.out.println("等级为1的产品A的method2()");
}
}
具体产品(等级为2的A产品):ConcreteProductA2类
[html] view
plain copy
//等级为2的具体产品A
public class ConcreateProductA2 implements ProductA {
@Override
public void method1() {
// TODO Auto-generated method stub
System.out.println("等级为2的产品A的method1()");
}
@Override
public void method2() {
// TODO Auto-generated method stub
System.out.println("等级为2的产品A的method2()");
}
}
具体产品(等级为1的B产品):ConcreteProductB1类
[html] view
plain copy
//等级为1的产品B
public class ConcreateProductB1 implements ProductB{
@Override
public void method1() {
// TODO Auto-generated method stub
System.out.println("等级为1的产品B的method1()");
}
@Override
public void method2() {
// TODO Auto-generated method stub
System.out.println("等级为1的产品B的method2()");
}
}
具体产品(等级为2的B产品):ConcreteProductB2类
[html] view
plain copy
//等级为2的产品B
public class ConcreateProductB2 implements ProductB {
@Override
public void method1() {
// TODO Auto-generated method stub
System.out.println("等级为2的产品B的method1()");
}
@Override
public void method2() {
// TODO Auto-generated method stub
System.out.println("等级为2的产品B的method2()");
}
}
运行结果:
等级为1的产品A的method1()
等级为1的产品A的method2()
等级为1的产品B的method1()
等级为1的产品B的method2()
等级为2的产品A的method1()
等级为2的产品A的method2()
等级为2的产品B的method1()
等级为2的产品B的method2()
总结:
抽象工厂模式相对于工厂方法模式来说,每个具体工厂可以生产一族产品(即多种产品);而工厂方法模式是具体工厂生产相应的具体产品,只能生产一种产品。当产品族中只有一种产品时抽象工厂模式退化成工厂方法模式。
16、状态模式
状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的逻辑判断简化,当判断状态很简单就不必要用。(1)State,抽象状态类,提供统一处理接口handle
(2)Context类,包含State引用,可以控制其指向父对象。构造函数完成状态初始化。request函数切换到具体状态的处理函数中。
(3)同时传入Context引用,在具体状态处理函数中,完成引用内容修改,调用request切换到接下来的状态处理。
State抽象状态类
<span style="font-size:12px;font-weight: normal;">package com.main; abstract class State { abstract void handle(Context context); } </span>Context
<span style="font-size:12px;font-weight: normal;">package com.main; public class Context { public State state; public Context(State state) { // TODO Auto-generated constructor stub this.state=state; } public void request(){ //此处传递的是引用,可以修改本身 state.handle(this); } } </span>
ConcreteStateA 具体状态类
<span style="font-size:12px;font-weight: normal;">package com.main; public class ConcreteStateA extends State{ @Override void handle(Context context) { // TODO Auto-generated method stub System.out.print("this is state of A\n"); context.state=new ConcreteStateB(); context.request(); } } </span>ConcreteStateB 具体状态类
<span style="font-size:12px;font-weight: normal;">package com.main; public class ConcreteStateB extends State{ @Override void handle(Context context) { // TODO Auto-generated method stub System.out.print("this is state of B\n"); } } </span>客户端代码:
<span style="font-size:12px;font-weight: normal;">package com.main; import java.io.Console; public class Main { public static void main(String[] args) { Context context=new Context(new ConcreteStateA()); context.request(); } } </span>输出:
this is state of A
this is state of B
17、适配器模式
适配器就是将一个接口换成另外一个接口,这中间就需要一个适配器类,继承目标抽象类。并在实现方法中完成转换。(1)Target类为目标类,给出需要适配器实现的方法。
(2)Adaptee需要适配的类。
(3)Adapter适配器,实现Target方法,并调用Adaptee的方法。
Target类
<span style="font-size:12px;font-weight: normal;">package com.main; abstract class Target { abstract void request(); } </span>Adaptee类
<span style="font-size:12px;font-weight: normal;">package com.main; public class Adaptee { public void specificRequest(){ System.out.print("this is specific request\n"); }; } </span>Adapter
<span style="font-size:12px;font-weight: normal;">package com.main; public class Adapter extends Target{ private Adaptee adaptee=new Adaptee(); @Override void request() { // TODO Auto-generated method stub adaptee.specificRequest(); } } </span>客户端代码:
<span style="font-size:12px;font-weight: normal;">package com.main; import java.io.Console; public class Main { public static void main(String[] args) { Target target=new Adapter() ; target.request(); } } </span>输出:
this is specific request
18、备忘录模式
备忘录:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原来的状态。适用于功能比较复杂的,但需要维护或记录属性历史的类,或者需要保存的属性只是众多属性的一小部分时,Originator可以根据保存的Memento信息还原到前一状态。
(1)Originator发起人类,用来控制需要保存的状态,具备设置备忘录功能,根据提供的备忘录,改变自身状态。同时具有concreteMemento创建备忘录函数,可以返回一个备忘录。
(2)返回的备忘录供管理者CareTaker保存。
Originator
<span style="font-size:12px;font-weight: normal;">package com.main; public class Originator { public String state; public Memento concreteMemento(){ return (new Memento(state)); } public void setMemento(Memento memento){ state=memento.state; } public void show(){ System.out.print(state+"\n"); } } </span>Memento
<span style="font-size:12px;font-weight: normal;">package com.main; public class Memento { public String state; public Memento(String state) { // TODO Auto-generated constructor stub this.state=state; } } </span>
CareTaker
<span style="font-size:12px;font-weight: normal;">package com.main; public class CareTaker { public Memento memento; } </span>客户端代码:
<span style="font-size:12px;font-weight: normal;">package com.main; import java.io.Console; public class Main { public static void main(String[] args) { Originator oritor=new Originator(); oritor.state="this is stateA"; oritor.show(); //保存至备忘录 CareTaker careTaker=new CareTaker(); careTaker.memento=oritor.concreteMemento(); oritor.state="this is stateB"; //利用备忘录还原 oritor.setMemento(careTaker.memento); oritor.show(); } } </span>输出:
this is stateA
this is stateA
19、组合模式
组合模式,将对象组合成树形结构以表示’部分-整体‘的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。(1)Component抽象类,管理子部件,并提供功能显示接口display
(2)Leaf类,不具有子部件,但提供功能显示
(3)Composite枝节点,具有子部件,同时提供功能显示。
Component
package com.main; abstract class Component { public String name; public Component(String name) { // TODO Auto-generated constructor stub this.name=name; } abstract void add(Component component); abstract void remove(Component component); abstract void display(); }Leaf
package com.main; public class Leaf extends Component { public Leaf(String name) { super(name); // TODO Auto-generated constructor stub } @Override void add(Component component) { // TODO Auto-generated method stub } @Override void remove(Component component) { // TODO Auto-generated method stub } @Override void display() { // TODO Auto-generated method stub System.out.print(name+"\n"); } }Composite
package com.main; import java.util.ArrayList; import java.util.List; public class Composite extends Component { private List<Component> children=new ArrayList<Component>(); public Composite(String name) { super(name); // TODO Auto-generated constructor stub } @Override void add(Component component) { // TODO Auto-generated method stub children.add(component); } @Override void remove(Component component) { // TODO Auto-generated method stub children.remove(component); } @Override void display() { // TODO Auto-generated method stub System.out.print(name+"\n"); for (Component component : children) { component.display(); } } }客户端代码:
package com.main; import java.io.Console; public class Main { public static void main(String[] args) { Composite root=new Composite("root"); root.add(new Leaf("leafA")); root.add(new Leaf("leafB")); Composite x=new Composite("x"); x.add(new Leaf("leafxA")); x.add(new Leaf("leafxB")); root.add(x); root.display(); } }输出:
root leafA leafB x leafxA leafxB透明方式与非透明方式:
透明方式为叶节点和枝节点具有同样的接口,这是透明方式,实际上,叶节点不需要实现add等操作,因此在component就不提供这些方法,只在composite
中实现。
20、迭代器模式
迭代器模式,提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。如链表等容器的迭代器一样。
21、单例模式
单例模式,保证一个类仅有一个实例,并提供一个访问它的全局访问点。通常可以让一个全局变量使得一个对象被访问,但它不能防止你实例化多个对象。一个最好的办法是,让类自身负责保存它的唯一实例。
这个类可以保证没有其它实例可以被创建,并可以提供一个访问该实例的方法。
分为懒汉式单例和饿汉式单例。
懒汉式单例:
package com.main; public class Singleton { <span style="white-space:pre"> </span>private Singleton(){} <span style="white-space:pre"> </span> private static Singleton instance; <span style="white-space:pre"> </span> public String data="222"; <span style="white-space:pre"> </span> private static Object object=new Object(); <span style="white-space:pre"> </span> public static Singleton getlnstance(){ <span style="white-space:pre"> </span> if(instance==null){ <span style="white-space:pre"> </span> synchronized(object){ <span style="white-space:pre"> </span> if(instance==null) <span style="white-space:pre"> </span> instance=new Singleton(); <span style="white-space:pre"> </span> } <span style="white-space:pre"> </span> return instance; <span style="white-space:pre"> </span> } <span style="white-space:pre"> </span> return instance; <span style="white-space:pre"> </span> } }客户端测试代码:
package com.main; import java.io.Console; public class Main { public static void main(String[] args) { new Thread(){ public void run() { Singleton s1=Singleton.getlnstance(); System.out.print(s1.data); while(true){ try { sleep(1000); System.out.print(s1.data); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }; }.start(); new Thread(){ public void run() { Singleton s2=Singleton.getlnstance(); s2.data="111"; }; }.start(); } }这里用两个线程,当第二个线程中改变单例数据时,第一个线程中的单例数据也改变。
输出:222111111111111111111111111111111111111
饿汉模式:
package com.main; public class Singleton { private Singleton(){ } public String data="222"; private static Singleton instance=new Singleton(); public static Singleton getlnstance(){ return instance; } }
利用客户端程序在不同线程中,结果是一样的。这样做更加方便。它是类一加载就实例化对象,提前占用资源,而懒汉模式则不是。
一般用饿汉模式就能满足要求。
22、桥接模式
对象的继承关系是在编译时就定义好了,所以无法无法在运行时改变从父类继承的实现,。子类的实现与它的父类有非常紧密的依赖关系,以至于父类实现中的任何变化必然导致子类发生变化。当你需要复用子类时,如果继承下来的实现不适合解决新的问题,则父类必须重写或被更合适的类替换。
这种依赖关系限制了灵活性并最终限制了复用性。
合成/聚合复用原则:尽量使用对象合成/聚合,而不是类继承。
聚合表示一种弱的’拥有‘关系,体现的是A对象可以包含B对象,但B对象不是A对象的一部分;合成则是一种强的’拥有‘关系,体现了严格的整体和部分的关系,
部分和整体的生命周期一样。
桥接模式:将抽象部分与它的实现部分分离,使他们都可以独立的变化。
(1)Implementor实现部分抽象类,可以有多重不同的实现。
(2)ConcreteImplementor具体实现类。
(3)Abstraction抽象部分类,可以设置不同的实现setImplementor,通过引用一个实现对象来完成。
(4)ConcreteAbstraction具体抽象类,调用实现对象的方法。
Implementor
package com.main; abstract class Implementor { public abstract void operation(); }ConcreteImplementorA
package com.main; public class ConcreteImplementorA extends Implementor{ @Override public void operation() { // TODO Auto-generated method stub System.out.print("this is implementor A\n"); } }Abstraction
package com.main; public abstract class Abstraction { public Implementor implementor; public void setImplementor(Implementor implementor){ this.implementor=implementor; } public abstract void operation(); }ConcreteAbstraction
package com.main; public class ConcreteAbstraction extends Abstraction{ @Override public void operation() { // TODO Auto-generated method stub implementor.operation(); } }客户端代码:
package com.main; import java.io.Console; public class Main { public static void main(String[] args) { Abstraction ab=new ConcreteAbstraction(); ab.setImplementor(new ConcreteImplementorA()); ab.operation(); ab.setImplementor(new ConcreteImplementorB()); ab.operation(); } }输出:
this is implementor A
this is implementor B
23、命令模式
命令模式,将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。优点:
容易实现命令队列。可以将命令记入日志。允许撤销和重做。新加入命令不影响其他类。隔离具体执行的操作,如用户只管下单和吃菜就可以了,不用通知师傅做菜。
(1)Receiver接收者,负责执行不同的命令操作,并提供接口供实际命令调用
(2)Command抽象命令类,提供构造函数,将命令绑定至接收者的引用,并提供抽象执行函数,让实际命令实现不同操作。
(3)ConcreteCommand实际命令,提供构造函数,初始化接收者引用,通知实现自己特有的执行函数--调用接收者函数执行。
(4)Invoker操作者,负责添加和执行命令,通过命令引用,调用命令的执行方法execute。这里应设置命令的多条添加和删除修改封装。
Receiver
<span style="font-weight: normal;">package com.main; public class Receiver { //根据不同的命令,这里应有不同的函数 public void action(){ System.out.print("command from concreteCommand"); } } </span>
Command
<span style="font-weight: normal;">package com.main; abstract class Command { protected Receiver receiver; public Command(Receiver receiver) { // TODO Auto-generated constructor stub this.receiver=receiver; } abstract void execute(); } </span>ConcreteCommand
<span style="font-weight: normal;">package com.main; public class ConcreteCommand extends Command { public ConcreteCommand(Receiver receiver) { super(receiver); // TODO Auto-generated constructor stub } @Override void execute() { // TODO Auto-generated method stub receiver.action(); } } </span>Invoker
<span style="font-weight: normal;">package com.main; public class Invoker { private Command command; public void setCommand(Command command){ this.command=command; } public void executeCommand(){ command.execute(); } } </span>客户端代码:
<span style="font-weight: normal;">package com.main; import java.io.Console; public class Main { public static void main(String[] args) { Receiver receiver=new Receiver(); //命令有很多种 Command command=new ConcreteCommand(receiver); Invoker invoker=new Invoker(); //通过invoker可以设置并执行命令 invoker.setCommand(command); invoker.executeCommand(); } }</span>输出:
command from concreteCommand
24、职责链模式
职责链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之见的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。(1)Handler抽象类,保存下一个处理者的引用,同时提供设置接口和处理请求接口,供不同处理者实现。
(2)ConcreteHandler具体处理者,实现自己的处理请求,如果处理不了,就交给下一个处理者。
Handler
<span style="font-weight: normal;">package com.main; abstract class Handler { protected Handler successor; public void setSuccessor(Handler successor){ this.successor=successor; } abstract void handleRequest(int request); } </span>ConcreteHandler
package com.main; public class ConcreteHandlerA extends Handler { @Override void handleRequest(int request) { // TODO Auto-generated method stub if(request<=10){ System.out.print("handle by A\n"); }else{ successor.handleRequest(request); } } }客户端代码:
package com.main; import java.io.Console; public class Main { public static void main(String[] args) { Handler handlerA=new ConcreteHandlerA(); Handler handlerB=new ConcreteHandlerB(); handlerA.setSuccessor(handlerB); handlerA.handleRequest(1); handlerA.handleRequest(11); } }输出:
handle by A
handle by B
25、中介者模式
中介者模式:用一个中介对象来封装一些列的对象交互。中介者使各对象不需要显示地相互引用,从而使其耦合松散,而且可以独立的改变它们之间的交互。(1)Mediator中介抽象类,提供抽象方法send,让实际中介实现。
(2)Colleague抽象类,包含中介引用
(3)ConcreteColleague 包含发送和接收函数,通过中介来发送消息,并定义接收函数。
(4)ConcreteMediator实际中介,提供发送函数,可以根据发送来的消息以及判断发送者,来通知特定的接收者。这里需要引用发送者,并在客户端实现。通过判断不同发送者,以通知不同的接收者,感觉这里有待改进?
Mediator
package com.main; abstract class Mediator { abstract void send(String message,Colleague colleague); }Colleague
package com.main; abstract class Colleague { public Mediator mediator; public Colleague(Mediator mediator) { // TODO Auto-generated constructor stub this.mediator=mediator; } }ConcreteColleague
package com.main; public class ConcreteColleagueA extends Colleague { public ConcreteColleagueA(Mediator mediator) { super(mediator); // TODO Auto-generated constructor stub } public void send(String message){ //注意这里的this传过去并非为了使用,只是告诉这个消息的发送者是谁 mediator.send(message, this); } public void notice(String message){ System.out.print("A get notice: "+message+"\n"); } }ConcreteMediator
package com.main; public class ConcreteMediator extends Mediator { <span style="white-space:pre"> </span>//在这里定义对象,其引用在客户端实现 <span style="white-space:pre"> </span>public ConcreteColleagueA colleagueA; <span style="white-space:pre"> </span>public ConcreteColleagueB colleagueB; <span style="white-space:pre"> </span>@Override <span style="white-space:pre"> </span>void send(String message, Colleague colleague) { <span style="white-space:pre"> </span>// TODO Auto-generated method stub <span style="white-space:pre"> </span>if(colleague==colleagueA){ <span style="white-space:pre"> </span>colleagueB.notice(message); <span style="white-space:pre"> </span>}else{ <span style="white-space:pre"> </span>colleagueA.notice(message); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} }客户端代码:
package com.main; import java.io.Console; public class Main { public static void main(String[] args) { ConcreteMediator mediator=new ConcreteMediator(); //实现双向绑定 ConcreteColleagueA colleagueA=new ConcreteColleagueA(mediator); ConcreteColleagueB colleagueB=new ConcreteColleagueB(mediator); mediator.colleagueA=colleagueA; mediator.colleagueB=colleagueB; colleagueA.send("hello i am collagueA nice to meet you"); colleagueB.send("i am collagueB nice to meet you too"); } }输出:
B get notice: hello i am collagueA nice to meet you
A get notice: i am collagueB nice to meet you too
26、享元模式
享元模式:运用共享技术有效地支持大量细粒度的对象。如果一些实例,除了几个参数外基本上是相同的,那么就将参数放在外面,如客户端,在调用方法的时候再传递进来这样,就可以将实例共享,大大减少单个实例的数目。其中外部参数叫做外部状态,而内部实例信息,叫做内部状态。
(1)FlyWeight享元抽象类,定义接口,可以对外部状态操作。
(2)ConcreteFlyWeight,实际享元类。实现操作外部状态的接口。
(3)UnsharedConcreteFlyWeight不共享的子类。
(4)FlyWeightFactory共享工厂,创造共享实例,供客户端调用。
FlyWeight
package com.main; abstract class FlyWeight { abstract void operation(String data); }ConcreteFlyWeight
package com.main; public class ConcreteFlyWeightA extends FlyWeight { @Override void operation(String data) { // TODO Auto-generated method stub System.out.print("this is shared A "+data+" \n"); } }UnsharedConcreteFlyWeight
package com.main; public class UnSharedConcretedFlyWeight extends FlyWeight { @Override void operation(String data) { // TODO Auto-generated method stub System.out.print("this is unshared"+data+"\n"); } }FlyWeightFactory
package com.main; import java.util.HashMap; import java.util.Hashtable; public class FlyWeightFactory { private Hashtable<String, FlyWeight> flyWeights=new Hashtable<String, FlyWeight>(); FlyWeightFactory(){ //两个不同实例,用来共享 flyWeights.put("flyWeightA", new ConcreteFlyWeightA()); flyWeights.put("flyWeightB", new ConcreteFlyWeightB()); } public FlyWeight getFlyWeight(String key){ return flyWeights.get(key); } }
客户端代码:
package com.main; import java.io.Console; public class Main { public static void main(String[] args) { FlyWeightFactory flyWeightFactory=new FlyWeightFactory(); //f1和f2共享一个实例 FlyWeight f1=flyWeightFactory.getFlyWeight("flyWeightA"); FlyWeight f2=flyWeightFactory.getFlyWeight("flyWeightA"); FlyWeight uf=new UnSharedConcretedFlyWeight(); //传入不同数据 f1.operation("f1"); f2.operation("f2"); uf.operation("uf"); } }输出:
this is shared A f1 this is shared A f2 this is unshareduf
27、解释器模式
解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。使用解释器,可方便的改变和扩展文法。但同样有不足,由于每一条规则至少定义一个类,因此若规则太多可能难以维护和管理。此时需要用别的专业的分析程序处理。
(1)AbstractExpression抽象表达式,提供一个解释操作
(2)TerminalExpression 终结符表达式实例。
(3)NonTerminalExpression非终结符表达式。
(4)Context 包含解释器之外的全局信息,这里用text替代。
AbstractExpression
package com.main; abstract class AbstractExpression { abstract void interpret(String text); }TerminalExpression
package com.main; public class TerminalExpression extends AbstractExpression { @Override void interpret(String text) { // TODO Auto-generated method stub System.out.print("terminal interpret:"+text+"\n"); } }NonTerminalExpression
package com.main; public class NonTerminalExpression extends AbstractExpression { @Override void interpret(String text) { // TODO Auto-generated method stub System.out.print("nonterminal interpret:"+text+"\n"); } }客户端代码:
package com.main; import java.io.Console; public class Main { public static void main(String[] args) { //根据一长段文本,根据不同类型,选择不同的解释器实例来解释 //这里只简单写一下 NonTerminalExpression nonTerExp=new NonTerminalExpression(); TerminalExpression TerExp=new TerminalExpression(); nonTerExp.interpret("aaa"); TerExp.interpret("bbb"); } }输出:
nonterminal interpret:aaa
terminal interpret:bbb
28、访问者模式
访问者模式:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。访问者模式适用于数据结构相对稳定的系统,它把数据结构和作用于结构上的操作之见的耦合解脱开,使得操作集合可以相对自由的演化。
即增加一个操作,只需要增加一个新的访问者,但缺点是增加新的结构变得困难了。
由于很难找到数据结构不变化的情况,所以本模式不常使用。
(1)Visitor访问者抽象类,为元素添加新的操作,这些操作可由不同的访问者来实现。
(2)ConcreteVisitor1访问者1,实现了自己的访问元素的操作。
(3)Element被访问元素抽象类,提供接收访问者的接口。
(4)ConcreteElement具体元素类,实现接收accept接口,根据传入Visitor引用,调用不同新的操作。
(5)ObjectStructure控制器,提供添加删除元素接口,并通过accept函数为这些元素添加访问者,从而调用不同新的操作。
Visitor
package com.main; abstract class Visitor { abstract void VistConcreteElementA(ConcreElementA elementA); abstract void VistConcreteElementB(ConcreElementB elementB); }ConcreteVisitor1
package com.main; public class ConcreteVistor1 extends Visitor { @Override void VistConcreteElementA(ConcreElementA elementA) { // TODO Auto-generated method stub System.out.print("new method to elementA from visitor1\n"); } @Override void VistConcreteElementB(ConcreElementB elementB) { // TODO Auto-generated method stub System.out.print("new method to elementB from visitor1\n"); } }Element
package com.main; abstract class Element { abstract void accept(Visitor visitor); }
ConcreteElementA
package com.main; public class ConcreElementA extends Element { @Override void accept(Visitor visitor) { // TODO Auto-generated method stub //此处为添加的新的方法,根据访问者不同,调用不同的方法 visitor.VistConcreteElementA(this); } public void operationA(){ //原来的方法 } }ObjectStructure
package com.main; import java.util.ArrayList; import java.util.List; public class ObjectStructure { private List<Element> elements=new ArrayList<Element>(); public void attach(Element element){ elements.add(element); } public void detach(Element element){ elements.remove(element); } public void accept(Visitor visitor){ for (Element element : elements) { element.accept(visitor); } } }客户端代码:
package com.main; import java.io.Console; public class Main { public static void main(String[] args) { ObjectStructure o=new ObjectStructure(); o.attach(new ConcreElementA()); o.attach(new ConcreElementB()); //相当于调用了Visitor中的两个新的方法 o.accept(new ConcreteVistor1()); } }输出:
new method to elementA from visitor1
new method to elementB from visitor1
[/b]
相关文章推荐
- [数位DP] BZOJ 4521 [Cqoi2016]手机号码
- Heap Sort ——重拾堆排序
- javaweb中如何将java.util.Date类型转换成java.sql.Date
- UVA 1149 Bin Packing 二分+贪心
- windows下批处理设置U盘盘符为U【非PE】
- 毕业设计(一)——择题,取材
- org.springframework.web.servlet.view.ContentNegotiatingViewResolver 配置
- ES Docs-3:Modifying Data
- Ubuntu14.04安装搜狗输入法
- Python学习笔记(三)——字符串
- sass的编译工具Koala
- solr入门之edismax权重排序使用之Java代码实现自定义权重
- Oracle笔记(十二) 集合、序列
- DAY3
- Spring MVC Controller中解析GET方式的中文参数会乱码的问题
- 每日站立会议(一)
- 【笔记】iOS开发基础笔记<四>
- 自定义View(三),仿支付宝芝麻信用自定义控件
- 初时mysql
- Hibernate 性能优化法则