开闭原则定义 :一个软件实体应当对扩展开放,对修改关闭。也就是说在设计一个模块的时候,应当使这个模块可以在不被修改的前提下被扩展。
开闭原则总结:面对需求,对程序的改动是通过增加新代码进行的,而不是改变原来的代码。
我们前面提到的模板方法模式和观察者模式都是开闭原则的极好体现
从到
代码如下(其实就是模板模式):
package
com.google.desingn;
//银行业务员接口,是所有银行业务员的抽象父类。
public interface BankWorker {
public void operation();
}
package com.google.desingn;
//负责存款业务的业务员
public class SavingBankWorker implements BankWorker {
public void operation() {
System.out.println("进行存款操作");
}
}
package package com.google.desingn;
// 负责取款业务的业务员
public class DrawingBankWorker implements BankWorker{
public void operation() {
System.out.println("进行取款操作");
}
}
package com.google.desingn;
public class TestClass {
public static void main(String[] args) {
BankWorker bankWorkerSave = new SavingBankWorker();
bankWorkerSave.operation();
BankWorker
bankWorkerDraw = new DrawingBankWorker();
bankWorkerDraw.operation();
}
}
# -*- coding:utf-8 -*- import struct def decode(x): #如果按照正常算法得到的synchsafe integer,解析成 真正的整数大小 a = x & 0xff; b = (x >> 8) & 0xff; c = (x >> 16) & 0xff; d = (x >> 24) & 0xff; x_final = 0x0; x_final = x_final | a; x_final = x_final | (b << 7); x_final = x_final | (c << 14); x_final = x_final | (d << 21); return x_final def encode(x): #和上边相反 a = x & 0x7f; b = (x >> 7) & 0x7f; c = (x >> 14) & 0x7f; d = (x >> 21) & 0x7f; x_final = 0x0; x_final = x_final | a; x_final = x_final | (b << 8); x_final = x_final | (c << 16); x_final = x_final | (d << 24); return x_final name = "4.mp3"; #要读取的文件 print name fp = open(name,'rb'); head = fp.read(10) id3,ver,revision,flag,length = struct.unpack("!3sBBBI",head); length = decode(length) print 'total:',length while True: frame = fp.read(10) fid,size,flag,flag2 = struct.unpack("!4sI2B",frame) if size==0: #有时候会留1024的白 不知道为啥 break if ver==4: #就是这一点 4和3的不同之处,4的这儿也采用synchsafe integer 了,注意啊 size = decode(size) print fid,'frame:',size fp.read(size) length-= (size+10) if length<=0: break #如果要给该mp3加张图片 那就方便了
找了一堆文章,走了许多弯路,发现许多同学的文档是错误滴,现在总结如下
虽然说 百度找来的每篇资料都说 现在的id3v2 都是3 版本,但是不知道是不是太古老啦,现在许多都四了噢,而且3和4有一点非常严重的不同,你如果把4当3来解,肯定会出错
参考文章
http://id3.org/id3v2.3.0
http://id3.org/id3v2.4.0-structure
http://fanzhichao.blog.hexun.com/28574021_d.html 这个是针对2.3的
通过克隆对象来创建一个新的对象叫做原型模式(prototype pattern)。原型模式属于创建设计模式的范畴,与它相对的单例模式(Singleton Pattern)相对,都很简单,也很常用。
使用场景:
1. 当有许多子类,并且仅仅是对象的类型不同而已。2. 引用程序中,需要创建大量的类实例且这些实例的状态等差异很小。
3. 动态的绑定或加重方法。
4. 使用一个实例,仅仅通过改变它的状态或参数去完成一个工作。
5. 在运行时,添加和删除对象。
6. 通过修改实例的结构来指定新对象。
7. 动态地用类配置一个应用程序。
需要记住的是:当使用clone去复制时,是否需要一个浅度克隆还是深度克隆(deep clone or shallow clone). 基于具体的业务需要,选择不同的克隆方式。如果你想使用深度克隆,你能够使用内存序列化( using in memory serialization)技术来实现。当实现原型设计模式时,使用克隆去复制完全是一个设计决策。请阅读如下例子。
public class Prototype { /** * Dynamic loading is a typical object-oriented feature and prototype example. * For example, overriding method is a kind of prototype pattern. */ static Complex c1 = new Complex(); /** * Cloning is a shallow copy of the original object. * If the cloned object is changed, the original object * will be changed accordingly. See the following alteration. * @return Complex */ static Complex makeCopy() { return (Complex)c1.clone(); } public static void main(String []args){ //Dynamically load method Shape s1 = new Line(); Shape s2 = new Square(); Shape s3 = new Circle(); paint(s1); paint(s2); paint(s3); /** * If we want to make code more readable or do more stuff, * we can code the paint method in the following way: static void paint(Shape s){ if ( s instanceof Line) s.draw(); //more job here if (s instanceof Square) s.draw(); //more job here if (s instanceof Circle) s.draw(); //more job here } */ Complex c1 = makeCopy(); int[] mycopy = c1.getNums(); for(int i = 0; i < mycopy.length; i++) System.out.print(mycopy[i]); } static void paint(Shape s) { s.draw(); } } interface Shape { public void draw(); } class Line implements Shape { public void draw() { System.out.println("line"); } } class Square implements Shape { public void draw() { System.out.println("square"); } } class Circle implements Shape { public void draw() { System.out.println("circle"); } } /** *The prototype is typically used to clone an object, * i.e. to make a copy of an object. When an object * is complicated or time consuming to be created , * you may take prototype pattern to make such object * cloneable. Assume the Complex class is a complicated, * you need to implement Cloneable interface and override * the clone method(protected Object clone()). */ class Complex implements Cloneable { int[] nums = {1,2,3,4,5}; public Object clone() { try { return super.clone(); }catch(CloneNotSupportedException cnse) { System.out.println(cnse.getMessage()); return null; } } int[] getNums() { return nums; } }
这个例子使用了prototype模式,减少了创建对象的花费(这个实例只是作为阐明原型设计模式,不能作为实际用途。)。值得使出的是, 对于原型模式而言,克隆不是一个强制的选择。
也许你感觉上面的例子不够接近实际应用,那么就认真看看下面的实例吧,也许能够在实际的项目中应用。
PrototypeCapable.java接口,扩展 Cloneable。
public interface PrototypeCapable extends Cloneable{ public PrototypeCapable clone() throws CloneNotSupportedException; }定义三个子类Album.java, Movie.java, Show.java, 实现PrototypeCapable接口。
public class Album implements PrototypeCapable{ private String name = null; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public Album clone() throws CloneNotSupportedException { System.out.println("Cloning Album object.."); return (Album) super.clone(); } @Override public String toString() { return "Album"; } }
public class Movie implements PrototypeCapable{ private String name = null; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public Movie clone() throws CloneNotSupportedException { System.out.println("Cloning Movie object.."); return (Movie) super.clone(); } @Override public String toString() { return "Movie"; } }
public class Show implements PrototypeCapable { private String name = null; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public Show clone() throws CloneNotSupportedException { System.out.println("Cloning Show object.."); return (Show) super.clone(); } @Override public String toString() { return "Show"; } }定义工厂类PrototypeFactory,根据类名字符克隆对象。
public class PrototypeFactory{ private static java.util.Map<String , PrototypeCapable> prototypes = new java.util.HashMap<String , PrototypeCapable>(); static{ prototypes.put(ModelType.MOVIE, new Movie()); prototypes.put(ModelType.ALBUM, new Album()); prototypes.put(ModelType.SHOW, new Show()); } public static PrototypeCapable getInstance(final String s) throws CloneNotSupportedException { return ((PrototypeCapable) prototypes.get(s)).clone(); } public static class ModelType { public static final String MOVIE = "movie"; public static final String ALBUM = "album"; public static final String SHOW = "show"; } }
测试这个类,测试代码如下:
import static org.junit.Assert.*; import junit.framework.Assert; import org.junit.After; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.pattern.rationaljava.creationalpattern.prototype.PrototypeFactory; import org.pattern.rationaljava.creationalpattern.prototype.PrototypeFactory.ModelType; public class TestPrototypeFactory { @BeforeClass public static void setUpBeforeClass() throws Exception { } @Before public void setUp() throws Exception { } @After public vo