一,迭代器模式
现在对于很多语言而言,这个模式已经不再需要自己定义去使用了。它们都封装了一个类的调用,用来遍历聚合对象中的元素内容。就拿Java来说,他有自己封装好的iterator类。迭代器模式的优点在于不暴露该聚合对象中的内部结构。这个模式的实现可以简单当做Iterator类的基本实现。
public abstract class MyIterator {
public abstract Object getFirst(); //第一个元素
public abstract Object getNext(); //获得下一个元素
public abstract Object CurrentItem(); //获得当前遍历结果
public abstract boolean isHasNext(); //是否已经到了结尾
}
public abstract class CreaIterator{
public abstract MyIterator createIterator();
}
public class MyIteratorAchive extends CreaIterator{
private List<Object> list = new ArrayList<Object>();
@Override
public MyIterator createIterator() {
return new UseMyIterator(new MyIteratorAchive());
}
public void setEle(Object object){
this.list.add(object);
}
public Integer getCount(){
return list.size();
}
public Object getEle(Integer index){
return list.get(index);
}
}
public class UseMyIterator extends MyIterator{
private MyIteratorAchive mita;
private Integer count =0 ;
public UseMyIterator(MyIteratorAchive mita) {
this.mita = mita;
}
@Override
public Object getFirst() {
return mita.getEle(0);
}
@Override
public Object getNext() {
++this.count;
Object obj = null;
if(this.count < mita.getCount()-1){
obj = mita.getEle(this.count);
}
return obj;
}
@Override
public Object CurrentItem() {
return mita.getEle(this.count);
}
@Override
public boolean isHasNext() {
if(this.count < mita.getCount()){
return true;
}
return false;
}
}
public class Main {
public static void main(String[] args) {
MyIteratorAchive mia = new MyIteratorAchive();
mia.setEle("haha");
mia.setEle("hehe");
mia.setEle("qieqie");
mia.setEle("wuwu");
UseMyIterator umi = new UseMyIterator(mia);
while(umi.isHasNext()==true){
System.out.println(umi.CurrentItem());
umi.getNext();
}
}
}
二,单例模式
保证一个类在该指定的过程中只存在一个实例,并且也只提供一个实例给予访问,这样的模式为单例模式。在《大话设计模式》有一个很好的例子,可以帮忙来理解。现在有一个工具,可以通过多种标签来打开窗口A,但是要求如果窗口A已经存在不能重复去打开。所以在每个标签的调用中,都需要去判断窗口A是否已经打开。然后关于一个生与不生都是自己的责任的问题 ,我们在编程的时候,对于窗口A的实例化,都应该是自己去实例化并且自己去关闭,而那些标签只是用来通知需要打开或关闭。如果不能理解,这样说吧。在公司,小明的报表马上就要完成了,这时候他遇见 了领导A问他完成了没有,他说完成了,然后之后又遇到了领导B问了同样的问题,也是回答完成了。但是事实上完成与否,只有小明自己知道。所以在这里窗口A的实例化与关闭都应该由自己来完成,而便签都只是起到一个类似于"查看状态"的作用。
关于单例模式,看以下代码。在网上看了很多实例,对于饿汉与懒汉没问题,但是如果涉及到单例模式,那么就需要考虑到同步的问题,只有一个实例的存在,这一点很重要。懒汉式中,为什么加了锁之后还要去判断一次,因为线程也会有存在抢占资源的问题,如果两个线程同时进入判断,那么等前一个线程lock,实例化,unlock之后,它任然可以再走一遍这样的操作。第二次判断是为了做到一个双重锁定的作用。
//懒汉式单例类
public class Singleton {
private static Singleton singleton;
private static Lock lock = new ReentrantLock();
private Singleton(){ //构造私有化,该类不能通过new建立对象
}
public static Singleton getInstance(){
if(singleton == null){
lock.lock();
if(singleton == null){
singleton = new Singleton();
lock.unlock();
}
}
return singleton;
}
}
//饿汉式
public class Singleton_2 {
private volatile static Singleton_2 singleton = new Singleton_2();
private Singleton_2(){
}
public static Singleton_2 getInstance(){
return singleton;
}
}
三,桥接模式
还是先说个例子,早期的手机的软件,与手机的型号有很大的匹配。编程实现,如果只是一个抽象类,包含了手机的软件与型号,如果后续要添加新的软件,那么需要修改的类太多,并不能达到复用的目的。抽象的使用原则是 "is a"原则,当出现这种多对多动态改变时就需要使用桥接模式,将抽象与实现分离,首先了解合成与聚合的定义,一只大雁,有两个翅膀,这是它的组成部分,一群大雁是聚合。看一下桥接模式实现的结构图。
这个模式让我想到了自己公司前段时间Intel来培训KVM,它们将不同电脑型号录入到xml文件中,与各种使用的内容,格式进行匹对,然后调用具体的封装好的类与方法与实现端口的集成管理,通过对xml的内容检索获取电脑型号去操作。虽然没有用到抽象集成,但是原理上与桥接差不太多。
public abstract class MobileVersion {
protected MobileSoft ms;
//设置软件
public void setMs(MobileSoft ms) {
this.ms = ms;
}
//运行
public abstract void run();
}
public abstract class MobileSoft {
public abstract void run();
}
public class MobileGame extends MobileSoft{
@Override
public void run() {
System.out.println("运行该手机游戏");
}
}
public class MobileB extends MobileVersion{
@Override
public void run() {
ms.run();
}
}
public class MobileA extends MobileVersion{
@Override
public void run() {
ms.run();
}
}
public class Main {
private static MobileVersion mv;
public static void main(String[] args) {
mv.setMs(new MobileGame());
mv = new MobileA();
mv.run();
mv = new MobileB();
mv.run();
}
}