更新时间2020/09/10:添加组合模式的优秀案例:
一个模式一个代码案例:总结一下。
1. 策略模式:
使用技巧:
- 他其实是一种多对一的关系,一个实体(类,页面),可以呈现不同的形态。
- 个人的经验,一定要设置默认策略
- 策略,建议考虑33原则,第一,有大于等于三种不同的形态,第二,有三种不同的行为,这样才能使用策略模式。
比如: 我有一个页面,三个地方跳转进来,要展示三种不同的view样式。同时里面有一个按钮,跳转三个不同的url,同时我还有一个请求,需要传递三种不同的参数。此时可以考虑。这种情况越多,越值得考虑。
能使用双向绑定化解的用双向绑定处理,更加规范清晰些。
- 注意一点,策略模式其实还牵涉到一个动态改变的问题,如果模型又动态改变的意思,那么将更加合适。
策略模式的主要优点如下。
多重条件语句不易维护,而使用策略模式可以避免使用多重条件语句(例如swtich case 或者连续的if else)。
策略模式提供了一系列的可供重用的算法族,恰当使用继承可以把算法族的公共代码转移到父类里面,从而避免重复的代码。
策略模式可以提供相同行为的不同实现,客户可以根据不同时间或空间要求选择不同的。
策略模式提供了对开闭原则的完美支持,可以在不修改原代码的情况下,灵活增加新算法。
策略模式把算法的使用放到环境类中,而算法的实现移到具体策略类中,实现了二者的分离。
其主要缺点如下。
客户端必须理解所有策略算法的区别,以便适时选择恰当的算法类。
策略模式造成很多的策略类。
2. 组合模式:
我之前写的应该不能叫做组合模式,顶多叫做组合。
组合模式的最大特点是可以取代父类。取代继承,比如本例中:operate2方法,可以是多个类的公共方法,也许这些方法,起初应该设计到父类里的,这里可以看到,他被以组合的形式添加到子类中。
3. 代理/委托模式
和策略模式相比,没有使用多态。直接使用代理类做事情。
package proxy;
public class ProxyTest
{
public static void main(String[] args)
{
Proxy proxy=new Proxy();
proxy.Request();
}
}
//抽象主题
interface Subject
{
void sellBaiFen();
}
//真实主题
class RealSubject implements Subject
{
public void sellBaiFen()
{
System.out.println("卖白粉");
}
}
//代理
class Proxy implements Subject
{
private RealSubject realSubject;
public void sellBaiFen()
{
if (realSubject==null)
{
realSubject=new RealSubject();
}
preRequest();
realSubject.sellBaiFen();
postRequest();
}
public void preRequest()
{
System.out.println("锡纸包裹,组成药丸的样子");
}
public void postRequest()
{
System.out.println("24小时售后");
}
}
4 . 观察者模式:
观察模式,这里使用原生api实现。包含三个类,天气数据类,天气展板类,主类(调用显示结果)
public class WeatherData extends Observable {
private float temperature;
private float pressure;
public WeatherData() {
}
public void setWeatherData(float temperature, float pressure) {
this.temperature = temperature;
this.pressure = pressure;
dataChanged();
}
private void dataChanged() {
setChanged();
notifyObservers();
}
public float getPressure() {
return pressure;
}
public float getTemperature() {
return temperature;
}
}
天气展板类
public class WeatherDisplay implements Observer {
Observable observable;
private float temperature;
private float pressure;
public WeatherDisplay(Observable observable) {
this.observable = observable;
observable.addObserver(this);
}
@Override
public void update(Observable observable, Object o) {
if (observable instanceof WeatherData){
WeatherData weatherData= (WeatherData) observable;
this.temperature=weatherData.getTemperature();
this.pressure=weatherData.getPressure();
display();
}
}
private void display() {
System.out.println("温度:"+temperature+"气压:"+pressure);
}
}
调用一下,看效果:
WeatherData weatherData=new WeatherData();
weatherData.setWeatherData(38f,1000f);
WeatherDisplay weatherDisplay=new WeatherDisplay(weatherData);
weatherDisplay.update(weatherData,this);
weatherData.setWeatherData(36f,1100f);
5. 装饰器模式:
先把需要的类贴在这里:
一共有四个类:1. 接口类,用来约束装饰的行为。2 ,具体实现类,实现接口所指明的行为
- 待装饰的类,使用具体装饰中的行为 4. 装饰类
现在将具体的几个类代码贴出来:
1>接口类
public interface Component {
void operate();
}
2>实现类
public class ContrateComponent implements Component {
public ContrateComponent() {
Log.d("ccccccccccccccccccc", "创建具体构建实体");
}
@Override
public void operate() {
Log.d("ccccccccccccccccccc", "调用具体构建方法");
}
}
3>待装饰类
特点:类将实现类作为构造的参数传递进来。
public class NeedDecorator implements Component {
Component component;
public NeedDecorator(Component component) {
this.component = component;
}
@Override
public void operate() {
component.operate();
}
}
4>装饰类
public class Role extends NeedDecorator {
public Role(Component component) {
super(component);
}
@Override
public void operate() {
super.operate();
addFunction();
}
public void addFunction(){
Log.d("cccccccccccccccccccc","为具体角色的增加额外的方法");
}
}
6. 外观模式:
意图:为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
主要解决:降低访问复杂系统的内部子系统时的复杂度,简化客户端与之的接口。
何时使用: 1、客户端不需要知道系统内部的复杂联系,整个系统只需提供一个"接待员"即可。 2、定义系统的入口。
如何解决:客户端不与系统耦合,外观类与系统耦合。
关键代码:在客户端和复杂系统之间再加一层,这一层将调用顺序、依赖关系等处理好。
应用实例: 1、去医院看病,可能要去挂号、门诊、划价、取药,让患者或患者家属觉得很复杂,如果有提供接待人员,只让接待人员来处理,就很方便。 2、JAVA 的三层开发模式。
优点: 1、减少系统相互依赖。 2、提高灵活性。 3、提高了安全性。
缺点:不符合开闭原则,如果要改东西很麻烦,继承重写都不合适。
使用场景: 1、为复杂的模块或子系统提供外界访问的模块。 2、子系统相对独立。 3、预防低水平人员带来的风险。
注意事项:在层次化结构中,可以使用外观模式定义系统中每一层的入口。
外观模式也是一种简单而又常用的模式。代码如下:
1>首先创建接口(模型的主要功能):
public interface Shape {
void draw();
}
2>创建三个实体,实现模型的功能
public class Square implements Shape {
@Override
public void draw() {
LogUtils.d("画square类型。。。。。");
}
}
3>创建一个外观类,里面拥有三个实体,并具有用三个方法,来实现三个实体的各自的draw功能。
public class ShapeMaker {
private Shape circle;
private Shape rectangle;
private Shape square;
public ShapeMaker() {
circle = new Circle();
rectangle = new Rectangle();
square = new Square();
}
public void drawCircle(){
circle.draw();
}
public void drawRectangle(){
rectangle.draw();
}
public void drawSquare(){
square.draw();
}
}
6. 原型模式:
主要解决:在运行期建立和删除原型。
public abstract class Shape implements Cloneable {
private String id;
protected String type;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
abstract void draw();
public Object clone() {
Object clone = null;
try {
clone = super.clone();
} catch (Exception e) {
e.printStackTrace();
}
return clone;
}
}
三个一摸一样的实现类
public class Square extends Shape {
public Square() {
type="square";
}
@Override
void draw() {
LogUtils.d("Sqarue draw 内部 ");
}
}
public class Rectangle extends Shape {
public Rectangle() {
type="Rectangle";
}
@Override
void draw() {
LogUtils.d("rrrrrrrrrrrrrrrr矩形内部");
}
}
public class Circle extends Shape {
public Circle() {
type="Circle";
}
@Override
void draw() {
LogUtils.d("circle 内部方法。");
}
}
public class ShapeCache {
private static Hashtable<String, Shape> shapeMap
= new Hashtable<String, Shape>();
public static Shape getShape(String shapeId) {
Shape cachedShape = shapeMap.get(shapeId);
return (Shape) cachedShape.clone();
}
// 对每种形状都运行数据库查询,并创建该形状
// shapeMap.put(shapeKey, shape);
// 例如,我们要添加三种形状
public static void loadCache() {
Circle circle = new Circle();
circle.setId("1");
shapeMap.put(circle.getId(),circle);
Square square = new Square();
square.setId("2");
shapeMap.put(square.getId(),square);
Rectangle rectangle = new Rectangle();
rectangle.setId("3");
shapeMap.put(rectangle.getId(),rectangle);
}
}
在main类里运行一下内容:
ShapeCache.loadCache();
Shape clonedShape = (Shape) ShapeCache.getShape("1");
LogUtils.d("Shape : " + clonedShape.getType());
Shape clonedShape2 = (Shape) ShapeCache.getShape("2");
LogUtils.d("Shape : " + clonedShape2.getType());
Shape clonedShape3 = (Shape) ShapeCache.getShape("3");
LogUtils.d("Shape : " + clonedShape3.getType());
7. 适配器模式:
1>首先定义一个接口,既具备播放vlc的功能,又具有播放MP4的功能
public interface AdvancedMediaPlayer {
void playVlc(String fileName);
void playMp4(String fileName);
}
定义两个类,各去实现其中一个功能:
public class Mp4Player implements AdvancedMediaPlayer {
@Override
public void playVlc(String fileName) {
}
@Override
public void playMp4(String fileName) {
System.out.println("Playing mp4 file. Name: "+ fileName);
}
}
vlcplayer功能
public class VlcPlayer implements AdvancedMediaPlayer {
@Override
public void playVlc(String fileName) {
System.out.println("Playing vlc file. Name: "+ fileName);
}
@Override
public void playMp4(String fileName) {
}
}
定义播放接口:
public interface MediaPlayer {
void play(String audioType, String fileName);
}
紧接着,真实的播放类实现这个接口,适配器也实现这个接口。
适配器适配这个播放接口,为了实现播放vlc和MP4,播放类实现此接口,因为本身需要这个功能,不多解释。
public class MediaAdapter implements MediaPlayer {
AdvancedMediaPlayer advancedMusicPlayer;
public MediaAdapter(String audioType){
if(audioType.equalsIgnoreCase("vlc") ){
advancedMusicPlayer = new VlcPlayer();
} else if (audioType.equalsIgnoreCase("mp4")){
advancedMusicPlayer = new Mp4Player();
}
}
@Override
public void play(String audioType, String fileName) {
if(audioType.equalsIgnoreCase("vlc")){
advancedMusicPlayer.playVlc(fileName);
}else if(audioType.equalsIgnoreCase("mp4")){
advancedMusicPlayer.playMp4(fileName);
}
}
}
播放类:播放类中传入adapter来播放那些指定的功能。
public class AudioPlayer implements MediaPlayer {
MediaAdapter mediaAdapter;
@Override
public void play(String audioType, String fileName) {
//播放 mp3 音乐文件的内置支持
if (audioType.equalsIgnoreCase("mp3")) {
System.out.println("Playing mp3 file. Name: " + fileName);
} else if (audioType.equalsIgnoreCase("vlc")
|| audioType.equalsIgnoreCase("mp4")) {
//mediaAdapter 提供了播放其他文件格式的支持
mediaAdapter = new MediaAdapter(audioType);
mediaAdapter.play(audioType, fileName);
} else {
System.out.println("Invalid media. " +
audioType + " format not supported");
}
}
}
在主类main方法中调用一下此功能。
AudioPlayer audioPlayer = new AudioPlayer();
audioPlayer.play("mp3", "beyond the horizon.mp3");
audioPlayer.play("mp4", "alone.mp4");
audioPlayer.play("vlc", "far far away.vlc");
audioPlayer.play("avi", "mind me.avi");
盘点一下,一共是两个接口类,一个是通用的播放接口,一个是显示其中具体格式的播放接口。
这个接口内部,又两种具体播放功能,播放mp4和vlc。
8. 享元模式:
创建一个shape:
public interface Shape {
void draw();
}
创建一个圆形,实现shape接口。
public class Circle implements Shape {
private String color;
private int x;
private int y;
private int radius;
public Circle(String color) {
this.color = color;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public void setRadius(int radius) {
this.radius = radius;
}
@Override
public void draw() {
System.out.println("Circle: Draw() [Color : " + color
+ ", x : " + x + ", y :" + y + ", radius :" + radius);
}
}
3>. 在运行类里面做工作:
private static final String colors[] =
{ "Red", "Green", "Blue", "White", "Black" };
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
for(int i=0; i < 20; ++i) {
Circle circle =
(Circle)ShapeFactory.getCircle(getRandomColor());
circle.setX(getRandomX());
circle.setY(getRandomY());
circle.setRadius(100);
circle.draw();
}
}
private static String getRandomColor() {
return colors[(int)(Math.random()*colors.length)];
}
private static int getRandomX() {
return (int)(Math.random()*100 );
}
private static int getRandomY() {
return (int)(Math.random()*100);
}
运行类的时候会发现,创建对象的次数只有5次,和数组的长度相同。
意图:运用共享技术有效地支持大量细粒度的对象。
主要解决:在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。
何时使用: 1、系统中有大量对象。 2、这些对象消耗大量内存。 3、这些对象的状态大部分可以外部化。 4、这些对象可以按照内蕴状态分为很多组,当把外蕴对象从对象中剔除出来时,每一组对象都可以用一个对象来代替。 5、系统不依赖于这些对象身份,这些对象是不可分辨的。
如何解决:用唯一标识码判断,如果在内存中有,则返回这个唯一标识码所标识的对象。
关键代码:用 HashMap 存储这些对象。
应用实例: 1、JAVA 中的 String,如果有则返回,如果没有则创建一个字符串保存在字符串缓存池里面。 2、数据库的数据池。
优点:大大减少对象的创建,降低系统的内存,使效率提高。
缺点:提高了系统的复杂度,需要分离出外部状态和内部状态,而且外部状态具有固有化的性质,不应该随着内部状态的变化而变化,否则会造成系统的混乱。
使用场景: 1、系统有大量相似对象。 2、需要缓冲池的场景。
注意事项: 1、注意划分外部状态和内部状态,否则可能会引起线程安全问题。 2、这些类必须有一个工厂对象加以控制。
9. 责任链模式:
责任链,链路上的类:
public abstract class Handler {
private Handler next;
public Handler getNext() {
return next;
}
public void setNext(Handler next) {
this.next = next;
}
public abstract void handlerRequest(String request);
}
链路 上的第一关:
public class ConcreteHandler1 extends Handler {
@Override
public void handlerRequest(String request) {
if (request.equals("one")){
System.out.println("具体处理者一负责处理该请求");
}else {
if (getNext()!=null){
getNext().handlerRequest(request);
}else {
System.out.println("没有人处理该请求");
}
}
}
}
链路上的第二关:
public class ConcreteHandler2 extends Handler {
@Override
public void handlerRequest(String request) {
if (request.equals("two")){
System.out.println("具体处理者二负责处理该请求");
}else {
if (getNext()!=null){
getNext().handlerRequest(request);
}else {
System.out.println("没有人处理该请求");
}
}
}
}
main方法中运行:
//组装责任链
Handler handler1=new ConcreteHandler1();
Handler handler2=new ConcreteHandler2();
handler1.setNext(handler2);
//提交请求
handler1.handlerRequest("two");
10. 命令模式:
public interface Order {
void execute();
}
买卖股票的类:
public class BuyStock implements Order {
private Stock abcStock;
public BuyStock(Stock abcStock) {
this.abcStock = abcStock;
}
@Override
public void execute() {
abcStock.buy();
}
}
卖股票的类:
public class SellStock implements Order {
public Stock abcStock;
public SellStock(Stock abcStock) {
this.abcStock = abcStock;
}
@Override
public void execute() {
abcStock.sell();
}
}
股票类:
public class Stock {
private String name = "ABC";
private int quantity = 10;
public void buy(){
System.out.println("name+"+name+"quantity"+quantity+"buy");
}
public void sell(){
System.out.println("name+"+name+"quantity"+quantity+"sell");
}
}
股票经理人类:
public class Broker {
private List<Order> orderList=new ArrayList<>();
public void takeOrder(Order order){
orderList.add(order);
}
public void placeOrders(){
for (Order order : orderList) {
order.execute();
}
orderList.clear();
}
}
main类中执行的具体方法:
Stock abcStock = new Stock();
BuyStock buyStockOrder = new BuyStock(abcStock);
SellStock sellStockOrder = new SellStock(abcStock);
Broker broker = new Broker();
broker.takeOrder(buyStockOrder);
broker.takeOrder(sellStockOrder);
broker.placeOrders();
11. 模板方法模式:
模板方法模式也是一种简单,常用的模式。
abstract class AbstractClass {
//模板方法
public void TemplateMethod(){
SpecificMethod();
abstractMethod1();
abstractMethod2();
}
//具体方法
public void SpecificMethod(){
System.out.println("抽象类中的具体方法被调用");
}
//抽象方法1
public abstract void abstractMethod1();
//抽象方法2
public abstract void abstractMethod2();
}
具体实现
public class ConcreteClass extends AbstractClass {
@Override
public void abstractMethod1() {
System.out.println("抽象方法1被调用");
}
@Override
public void abstractMethod2() {
System.out.println("抽象方法2被调用");
}
}
main类中的方法:
AbstractClass tm=new ConcreteClass();
tm.TemplateMethod();
可以看到:
1>它封装了不变部分,扩展可变部分。它把认为是不变部分的算法封装到父类中实现,而把可变部分算法由子类继承实现,便于子类继续扩展。
2>它在父类中提取了公共的部分代码,便于代码复用。
3>部分方法是由子类实现的,因此子类可以通过扩展方式增加相应的功能,符合开闭原则。
例如,去银行办理业务一般要经过以下4个流程:取号、排队、办理具体业务、对银行工作人员进行评分等,其中取号、排队和对银行工作人员进行评分的业务对每个客户是一样的,可以在父类中实现,但是办理具体业务却因人而异,它可能是存款、取款或者转账等,可以延迟到子类中实现。
这样的例子在生活中还有很多,例如,一个人每天会起床、吃饭、做事、睡觉等,其中“做事”的内容每天可能不同。我们把这些规定了流程或格式的实例定义成模板,允许使用者根据自己的需求去更新它,例如,简历模板、论文模板、Word 中模板文件等。
和一般的写法有什么不同:
1>具体实现在子类中进行,面向功能的类不臃肿。这其实是依赖倒置。面向接口编程。
2> 父类中固定了一些方法,又开放了一些抽象的方法,让子类实现。这其实也符合某种现实世界,比如有些业务,对所有的子类都一样,那么在父类中实现。那些不具有一般性的功能,开放给子类,让子类实现。
12. 单例模式:
简单点说,就是一个应用程序中,某个类的实例对象只有一个,你没有办法去new,因为构造器是被private修饰的,一般通过getInstance()的方法来获取它们的实例。
getInstance()的返回值是一个对象的引用,并不是一个新的实例,所以不要错误的理解成多个对象。单例模式实现起来也很容易,直接看demo吧
public class Singleton {
private static Singleton singleton;
private Singleton() {
}
public static Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
按照我的习惯,我恨不得写满注释,怕你们看不懂,但是这个代码实在太简单了,所以我没写任何注释,如果这几行代码你都看不明白的话,那你可以洗洗睡了,等你睡醒了再来看我的博客说不定能看懂。
上面的是最基本的写法,也叫懒汉写法(线程不安全)下面我再公布几种单例模式的写法:
懒汉式写法(线程安全)
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
饿汉式写法
单例模式很多代理代码了,重点是理解他的特点和场景。
13. 建造者模式:
此模式也比较常见,至少在安卓的源码,以及一些开源项目种十分多见。
public abstract class Builder {
//创建产品对象
protected Product product=new Product();
public abstract void buildPartA();
public abstract void buildPartB();
public abstract void buildPartC();
//返回产品对象
public Product getResult()
{
return product;
}
}
实体的类
public class ConcreteBuilder extends Builder {
@Override
public void buildPartA() {
product.setPartA("建造 PartA");
}
@Override
public void buildPartB() {
product.setPartB("建造 PartB");
}
@Override
public void buildPartC() {
product.setPartC("建造 PartC");
}
}
public class Director {
private Builder builder;
public Director(Builder builder)
{
this.builder=builder;
}
//产品构建与组装方法
public Product construct()
{
builder.buildPartA();
builder.buildPartB();
builder.buildPartC();
return builder.getResult();
}
}
public class Product {
private String partA;
private String partB;
private String partC;
public void setPartA(String partA)
{
this.partA=partA;
}
public void setPartB(String partB)
{
this.partB=partB;
}
public void setPartC(String partC)
{
this.partC=partC;
}
public void show()
{
System.out.println("产品有这些部分"+partA+partB+partC);
}
}
main方法里面:
Builder builder = new ConcreteBuilder();
Director director = new Director(builder);
Product product = director.construct();
product.show();
14. 状态模式:
public abstract class State {
public abstract void Handle(Context context);
}
实现类:
public class ConcreteStateA extends State {
@Override
public void Handle(Context context) {
System.out.println("当前状态是 A.");
context.setState(new ConcreteStateB());
}
}
public class ConcreteStateB extends State {
@Override
public void Handle(Context context) {
System.out.println("当前状态是B");
context.setState(new ConcreteStateA());
}
}
环境类:
public class Context {
private State state;
public Context() {
this.state = new ConcreteStateA();
}
//设置新状态
public void setState(State state)
{
this.state=state;
}
//读取状态
public State getState()
{
return(state);
}
//对请求做处理
public void Handle()
{
state.Handle(this);
}
}
main 入口中的代码:
Context context=new Context(); //创建环境
context.Handle(); //处理请求
context.Handle();
context.Handle();
context.Handle();
22. 迭代器模式:
这个模型代码其实,就是我们常用的一个迭代器.
迭代器(Iterator)模式的定义:提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。迭代器模式是一种对象行为型模式,其主要优点如下。
访问一个聚合对象的内容而无须暴露它的内部表示。
遍历任务交由迭代器完成,这简化了聚合类。
它支持以不同方式遍历一个聚合,甚至可以自定义迭代器的子类以支持新的遍历。
增加新的聚合类和迭代器类都很方便,无须修改原有代码。
封装性良好,为遍历不同的聚合结构提供一个统一的接口。
其主要缺点是:增加了类的个数,这在一定程度上增加了系统的复杂性。
结构如下:
抽象聚合(Aggregate)角色:定义存储、添加、删除聚合对象以及创建迭代器对象的接口。
具体聚合(ConcreteAggregate)角色:实现抽象聚合类,返回一个具体迭代器的实例。
抽象迭代器(Iterator)角色:定义访问和遍历聚合元素的接口,通常包含 hasNext()、first()、next() 等方法。
具体迭代器(Concretelterator)角色:实现抽象迭代器接口中所定义的方法,完成对聚合对象的遍历,记录遍历的当前位置。
模式代码:
public interface Aggregate {
void add(Object obj);
void remove(Object obj);
Iterator getIterator();
}
具体聚合对象
public class ConcreteAggregate implements Aggregate {
private List<Object> list = new ArrayList<Object>();
@Override
public void add(Object obj) {
list.add(obj);
}
@Override
public void remove(Object obj) {
list.remove(obj);
}
@Override
public Iterator getIterator() {
return (Iterator) new ConcreteIterator(list);
}
}
具体:ConcreteIterator
public class ConcreteIterator implements Iterator {
private List<Object> list;
private int index=-1;
public ConcreteIterator(List<Object> list) {
this.list = list;
}
@Override
public boolean hasNext() {
if (index<list.size()-1){
return true;
}else {
return false;
}
}
@Override
public Object first() {
index=0;
Object obj=list.get(index);
return obj;
}
@Override
public Object next() {
Object obj=null;
if (this.hasNext()){
obj=list.get(++index);
}
return obj;
}
}
public interface Iterator {
Object first();
Object next();
boolean hasNext();
}
main方法内部要执行的内容:
Aggregate ag = new ConcreteAggregate();
ag.add("中山大学");
ag.add("华南理工");
ag.add("韶关学院");
System.out.print("聚合的内容有:");
Iterator it = ag.getIterator();
while (it.hasNext()) {
Object ob = it.next();
System.out.print(ob.toString() + "\t");
}
Object ob = it.first();
System.out.println("\nFirst:" + ob.toString());
23. 解释器模式:
目前个人感觉还是比较难以理解的模式,好多教材中都是最后。
1>表达的接口
public interface Expression {
boolean interpret(String context);
}
2>终端表达类实现这个接口:
public class TerminalExpression implements Expression {
private String data;
public TerminalExpression(String data){
this.data = data;
}
@Override
public boolean interpret(String context) {
if(context.contains(data)){
return true;
}
return false;
}
}
3>具体表达类,这里是and 或者or的两种:
构造的时候需要传入两个表达对象
public class AndExpression implements Expression {
private Expression expr1 = null;
private Expression expr2 = null;
public AndExpression(Expression expr1, Expression expr2) {
this.expr1 = expr1;
this.expr2 = expr2;
}
@Override
public boolean interpret(String context) {
return expr1.interpret(context) && expr2.interpret(context);
}
}
另外一个Or的形式:
public class OrExpression implements Expression {
private Expression expr1 = null;
private Expression expr2 = null;
public OrExpression(Expression expr1, Expression expr2) {
this.expr1 = expr1;
this.expr2 = expr2;
}
@Override
public boolean interpret(String context) {
return expr1.interpret(context) || expr2.interpret(context);
}
}
main 入口类里又两个方法:
//规则:Robert 和 John 是男性
public static Expression getMaleExpression(){
Expression robert = new TerminalExpression("Robert");
Expression john = new TerminalExpression("John");
return new OrExpression(robert, john);
}
//规则:Julie 是一个已婚的女性
public static Expression getMarriedWomanExpression(){
Expression julie = new TerminalExpression("Julie");
Expression married = new TerminalExpression("Married");
return new AndExpression(julie, married);
}
main方法内部代码:
Expression isMale = getMaleExpression();
Expression isMarriedWoman = getMarriedWomanExpression();
System.out.println("John is male? " + isMale.interpret("John"));
System.out.println("Julie is a married women? "
+ isMarriedWoman.interpret("Married Julie"));
网友评论