.net 网站开发 教程wordpress 头像 virtos

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

.net 网站开发 教程,wordpress 头像 virtos,512内存服务器做网站,电影网-个人网站建设论文文章目录 一、代理模式1.静态代理2.JDK动态代理3.CGLib动态代理4.三种代理对比 二、适配器模式1.类适配器模式2.对象适配器模式 三、装饰者模式静态代理和装饰者的区别 四、桥接模式五、外观模式六、组合模式七、享元模式 结构性模式描述如何将类或对象按某种布局组成更大的结构… 文章目录 一、代理模式1.静态代理2.JDK动态代理3.CGLib动态代理4.三种代理对比 二、适配器模式1.类适配器模式2.对象适配器模式 三、装饰者模式静态代理和装饰者的区别 四、桥接模式五、外观模式六、组合模式七、享元模式 结构性模式描述如何将类或对象按某种布局组成更大的结构。分为类结构型模式采用继承机制来组织接口和类对象结构型模式采用组合或聚合来组合对象。耦合度更低满足合成复用原则一、代理模式 由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时访问对象不适合或不能直接引用目标对象 代理对象作为访问对象和目标对象之间的中介。java中的代理按照代理类生成时机不同分为静态代理和动态代理。 静态代理代理类在编译期生成 动态代理在运行时动态生成。又分为JDK代理和CGLib代理角色抽象主题类通过接口或抽象类声明真实主题和代理对象实现的业务方法真实主题类实现了抽象主题中的具体业务是代理对象所代表的真实对象是最终要引用的对象代理类提供了与真实主题相同的接口其内部含有对真实主题的引用它可以访问、控制或拓展真实主题的功能优点代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用代理对象可以扩展目标对象的功能代理模式能将客户端与目标对象分离在一定程度上降低了系统的耦合度缺点增加了系统的复杂度使用场景a.远程代理本地服务通过网络请求远程服务。为了实现本地到远程的通信我们需要实现网络通信处理其中可能的异常。为了良好的代码设计和可维护性我们将网络通信部分隐藏起来只暴露给本地服务一个接口通过该接口即可访问远程服务提供的功能而不必过多关心通信部分的细节b.防火墙代理将浏览器配置成使用代理功能时防火墙就将浏览器的请求转发给互联网当互联网返回响应时代理服务器再把它转给浏览器c.保护代理控制对一个对象的访问如果需要可以给不同的用户提供不同级别的使用权限1.静态代理 /*** 抽象主题类 : 买火车票的接口/ public interface SellTickets {void sell();}/** 真实主题类 : 火车站类/ public class TrainStation implements SellTickets{Overridepublic void sell() {System.out.println(火车站卖票);} }/** 代理类 : 代售点类/ public class ProxyPoint implements SellTickets{//声明火车站类对象private TrainStation station new TrainStation();Overridepublic void sell() {System.out.println(这里是代售点,需要10块钱服务费);station.sell();} }public class Client {public static void main(String[] args) {ProxyPoint proxyPoint new ProxyPoint();proxyPoint.sell();}}2.JDK动态代理 java中提供了一个动态代理类ProxyProxy中提供了 newProxyInstance() 来获取代理对象执行流程 在测试类中通过对象调用sell()方法 根据多态的特性执行的是代理类(\(Proxy0)中的sell()方法 代理类(\)Proxy0)中的sell()方法中又调用了InvocationHandler接口的自实现类对象的invake方法 invake方法通过反射执行了真实对象所属类(TrainStation)中的sell()方法/** 抽象主题类 : 买火车票的接口/ public interface SellTickets {void sell();}/** 真实主题类 : 火车站类/ public class TrainStation implements SellTickets {Overridepublic void sell() {System.out.println(火车站卖票);} }/** 获取代理对象的工厂类* 代理类也实现了对应的接口/ public class ProxyFactory {//声明目标对象private TrainStation station new TrainStation();public SellTickets getProxyObject(){/** ClassLoader loader : 类加载器,用于加载代理类,可以通过目标对象获取类加载器* Class?[] interfaces : 代理类实现的接口的字节码对象* InvocationHandler h : 代理对象的调用处理程序/SellTickets proxyInstance (SellTickets) Proxy.newProxyInstance(station.getClass().getClassLoader(),station.getClass().getInterfaces(),new InvocationHandler() {/** proxy : 代理对象 和proxyInstance是同一个对象,在invoke中基本不用* method : 对接口中的方法进行封装的method对象* args : 调用方法的实际参数* 返回值 : 方法的返回值/Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println(代售点收取10块钱服务费);//执行目标对象的方法Object obj method.invoke(station, args);return obj;}});return proxyInstance;}}public class Client {public static void main(String[] args) {//获取代理对象ProxyFactory factory new ProxyFactory();SellTickets proxy factory.getProxyObject();proxy.sell();}}3.CGLib动态代理 需要引入第三方jar包为没有实现接口的类提供代理CGLib底层采用ASM字节码生成框架使用字节码技术/** 代理对象工厂/ public class ProxyFactory implements MethodInterceptor {private TrainStation station new TrainStation();public TrainStation getProxyObject() {//类似于JDK代理中的Proxy类Enhancer enhancer new Enhancer();//设置父类的字节码对象enhancer.setSuperclass(TrainStation.class);//设置回调函数enhancer.setCallback(this);//创建代理对象TrainStation proxyObject (TrainStation) enhancer.create();return proxyObject;}Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)throws Throwable {System.out.println(代售点坑人);//调用目标对象的方法Object obj method.invoke(station, objects);return obj;} }/** 真实主题类 : 火车站类/ public class TrainStation{public void sell() {System.out.println(火车站卖票);}}public class Client {public static void main(String[] args) {//创建代理工厂对象ProxyFactory factory new ProxyFactory();//获取代理对象TrainStation proxy factory.getProxyObject();//调用代理对象中的sell卖票proxy.sell();}}4.三种代理对比 JDK和CGLIB CGLIB底层采用ASM字节码生成框架使用字节码技术生成代理类在JDK1.6之前比使用java反射效率要高。 但是CGLIB不能对声明为final的类或者方法进行代理因为CGLIB原理是动态生成被代理类的子类。 在JDK1.8的时候JDK的效率高于CGLIB。 所以如果有接口就使用JDK代理没有的话使用CGLIB代理静态代理和动态代理 动态代理最大的好处就是接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理。 这样在接口方法数量比较多的时候我们可以灵活处理而不需要像静态代理那样每一个方法进行中转 如果接口增加一个方法静态代理模式除了所有实现类需要实现这个方法外所有代理类也需要实现此方法。 增加了代码维护的复杂度而动态代理不会出现该问题二、适配器模式 将一个类的接口转换成客户希望的另外一个接口使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。分类类适配器耦合度较高要求了解现有组件库中的相关组件的内部结构所以应用相对较少对象适配器结构目标接口当前系统业务所期待的接口它可以是抽象类或接口适配者类它是被访问和适配的现存组件库中的组件接口适配器类它是一个转换器通过继承或引用适配者的对象把适配者接口转换成目标接口让客户按目标接口的访问格式访问适配者应用场景以前开发地系统存在满足新系统功能需求的类但是其接口同新系统的接口不一致使用第三方提供的组件但组件接口定义和自己要求的接口定义不同1.类适配器模式 实现方式定义一个适配器类来实现当前系统的业务接口同时又继承现有组件库中已经存在的组件违背了合成复用原则在客户类有一个接口规范的情况下可以使用如果没有就不能使用/** 目标接口/ public interface SDCard {String readSD();void writeSD(String msg); }/** 具体类/ public class SDCardImpl implements SDCard{Overridepublic String readSD() {return 从SD卡读取数据;}Overridepublic void writeSD(String msg) {System.out.println(向SD卡写入数据 : msg);} }/** 适配者类的接口/ public interface TFCard {String read();void write(String msg);}/** 适配者类/ public class TFCardImpl implements TFCard{Overridepublic String read() {return TFCard读取了数据;}Overridepublic void write(String msg) {System.out.println(TFCard写入了数据 : msg);} }/** 适配器类/ public class SDAdapterTF extends TFCardImpl implements SDCard{Overridepublic String readSD() {System.out.println(adapter read TFCard);return read();}Overridepublic void writeSD(String msg) {System.out.println(adapter write TFCard);write(msg);} }/** 计算机类/ public class Computer {//从SD卡中读取数据public String readSD(SDCard sdCard){if (sdCard null){throw new NullPointerException(SDCard is not null);}return sdCard.readSD();}}public class Client {public static void main(String[] args) {Computer computer new Computer();String s computer.readSD(new SDCardImpl());System.out.println(s);System.out.println();String msg computer.readSD(new SDAdapterTF());System.out.println(msg);}}2.对象适配器模式 不再去继承适配者类而且聚合/** 适配器类/ public class SDAdapterTF implements SDCard {//声明适配者类private TFCard tfCard;public SDAdapterTF(TFCard tfCard){this.tfCard tfCard;}Overridepublic String readSD() {System.out.println(adapter read TFCard);return tfCard.read();}Overridepublic void writeSD(String msg) {System.out.println(adapter write TFCard);tfCard.write(msg);} }三、装饰者模式 指在不改变现有对象结构的情况下动态地给该对象增加一些功能的模式结构抽象构件角色定义一个抽象接口以规范准备接收附加责任的对象具体构件角色实现抽象构件通过装饰角色为其添加一些职责抽象装饰角色继承或实现抽象构件并包含具体构件的实例可以通过其子类扩展具体构件的功能具体装饰角色实现抽象装饰的相关方法并给具体构件对象添加附加的责任优点1.装饰者模式可以带来比继承更加灵活性的扩展功能使用更加方便可以通过组合不同的装饰者对象来获取具有不同行为状态的多样化结果。装饰者模式比继承更具良好的扩展性完美的遵循开闭原则继承是静态的附加责任装饰者则是动态地附加责任2.装饰类和被装饰类可以独立发展不会相互耦合装饰者模式是继承的一个替代模式装饰模式可以动态扩展一个实现类的功能使用场景1.当不能采用继承的方式对系统进行扩展或者采用继承不利于系统扩展和维护时不能采用继承系统中存在大量独立的扩展为支持每一种组合将产生大量的子类类被定义为final2.在不影响其它对象的情况下以动态、透明的方式给单个对象添加职责3.当对象的功能要求可以动态地添加也可以动态地撤销时 /** 抽象构件角色 快餐类/ public abstract class FastFood {private float price;private String desc;public FastFood(){}public FastFood(float price, String desc) {this.price price;this.desc desc;}public float getPrice() {return price;}public void setPrice(float price) {this.price price;}public String getDesc() {return desc;}public void setDesc(String desc) {this.desc desc;}public abstract float cost(); }/** 具体构件角色 炒饭/ public class FriedRice extends FastFood{private static final float price 10;private static final String desc 炒饭;public FriedRice(){super(price,desc);}Overridepublic float cost() {return super.getPrice();} }/** 具体构件角色 炒面/ public class FiredNoodles extends FastFood{private static final float price 12;private static final String desc 炒面;public FiredNoodles(){super(price,desc);}Overridepublic float cost() {return super.getPrice();} }/** 抽象装饰角色/ public abstract class Garnish extends FastFood{//声明快餐类的变量private FastFood fastFood;public Garnish(float price, String desc, FastFood fastFood) {super(price, desc);this.fastFood fastFood;}public FastFood getFastFood() {return fastFood;}public void setFastFood(FastFood fastFood) {this.fastFood fastFood;} }/** 具体装饰者角色/ public class Egg extends Garnish{private static final float price 1;private static final String desc 鸡蛋;public Egg(FastFood fastFood){super(price,desc,fastFood);}Overridepublic float cost() {//计算价格return price super.getFastFood().cost();}Overridepublic String getDesc() {return desc super.getFastFood().getDesc();} }/** 具体装饰者角色/ public class Bacon extends Garnish{private static final float price 3;private static final String desc 培根;public Bacon(FastFood fastFood){super(price,desc,fastFood);}Overridepublic float cost() {//计算价格return price super.getFastFood().cost();}Overridepublic String getDesc() {return desc super.getFastFood().getDesc();} }public class Test {public static void main(String[] args) {//炒饭FastFood food new FriedRice();System.out.println(food.getDesc() food.cost() 元);System.out.println(———————);//加鸡蛋food new Egg(food);System.out.println(food.getDesc() food.cost() 元);System.out.println(———————);//再加鸡蛋food new Egg(food);System.out.println(food.getDesc() food.cost() 元);System.out.println(———————);//再加培根food new Bacon(food);System.out.println(food.getDesc() food.cost() 元);}}静态代理和装饰者的区别 相同点1.都要实现与目标类相同的业务接口2.在两个类中都要声明目标对象3.都可以在不修改目标类的前提下增强目标方法不同点:1.目的不同装饰者是为了增强目标对象静态代理是为了保护和隐藏目标对象2.获取目标对象构建的地方不同装饰者是由外界传递进来可以通过构造方法传递静态代理是在代理类内部创建以此来隐藏目标对象四、桥接模式 将抽象与实现分离使他们可以独立变化。它是用组合关系代替继承关系来实现从而降低了抽象和实现这两个 可变维度的耦合度结构抽象化角色定义抽象类并包含一个对实现化对象的引用扩展抽象化角色是抽象化角色的子类实现父类中的业务方法并通过组合关系调用实现化角色中的业务方法实现化角色定义实现化角色的接口供扩展抽象化角色调用具体实现化角色给出实现化角色接口的具体实现优点1.提高了系统的可扩充性在两个变化维度中任意扩展一个维度都不需要修改原有系统2.实现细节对客户透明使用场景1.当一个类存在两个独立变化的维度且这两个维度都需要进行扩展时2.当一个系统不希望使用继承或其它多层次继承导致类的个数急剧增加时3.当一个系统需要在构件的抽象化和具体角色之间增加更多的灵活性时。避免在两个层次之间建立静态的继承联系通过桥接模式可以使他们在抽象层建立一个关联关系/** 实现化角色/ public interface VideoFile {//解码void decode(String fileName);}/** 具体实现化角色/ public class AVIFile implements VideoFile{Overridepublic void decode(String fileName) {System.out.println(avi视频文件 : fileName);} }/** 具体实现角色/ public class RMVBFile implements VideoFile{Overridepublic void decode(String fileName) {System.out.println(rmvb视频文件 : fileName);} }/** 抽象化角色/ public abstract class OpratingSystem {public VideoFile videoFile;public OpratingSystem(VideoFile videoFile){this.videoFile videoFile;}public abstract void play(String fileName);}/** 扩展抽象化角色/ public class Windows extends OpratingSystem{public Windows(VideoFile videoFile) {super(videoFile);}Overridepublic void play(String fileName) {videoFile.decode(fileName);} }/** 扩展抽象化角色/ public class Mac extends OpratingSystem{public Mac(VideoFile videoFile) {super(videoFile);}Overridepublic void play(String fileName) {videoFile.decode(fileName);} }public class Test {public static void main(String[] args) {OpratingSystem system new Mac(new AVIFile());system.play(飞升.avi);}}五、外观模式 一种通过为多个复杂的子系统提供一个一致的接口而使这些子系统更加容易被访问的模式。 该模式对外有一个统一的接口外部应用程序不用关心内部子系统的具体的细节 这样会大大降低应用程序的复杂度提高程序的可维护性。 是迪米特法则的典型应用结构外观角色为多个子系统对外提供一个公共的接口子系统角色实现系统的部分功能外部可以通过外观角色访问它优点1.降低了子系统和客户端之间的耦合度使得子系统的变化不会影响调用它的类2.对客户屏蔽了子系统组件减少了客户处理的对象的数目并使得子系统使用起来更加容易缺点不符合开闭原则修改很麻烦使用场景1.对分层结构系统构建时使用外观模式定义子系统中每层的入口点可以简化子系统之间的依赖关系2.当一个复杂系统的子系统很多时外观模式可以为系统设计一个简单的接口供外界访问3.当客户端与多个子系统之间存在很大的联系时引入外观模式可将它们分离从而提高子系统的独立性和可移植性/** 子系统角色/ public class Light {public void on(){System.out.println(打开灯);}public void off(){System.out.println(关闭灯);}}/** 子系统角色/ public class TV {public void on(){System.out.println(打开电视);}public void off(){System.out.println(关闭电视);}}/** 子系统角色/ public class AirCondition {public void on(){System.out.println(打开空调);}public void off(){System.out.println(关闭空调);}}/** 外观角色/ public class SmartAppliancesFacade {private Light light;private TV tv;private AirCondition airCondition;public SmartAppliancesFacade() {light new Light();tv new TV();airCondition new AirCondition();}public void say(String msg){if (msg.contains(打开)){this.on();} else if (msg.contains(关闭)) {this.off();} else {System.out.println(请说出正确指令);}}private void on(){light.on();airCondition.on();tv.on();}private void off(){light.off();airCondition.off();tv.off();} }public class Test {public static void main(String[] args) {SmartAppliancesFacade smart new SmartAppliancesFacade();smart.say(把他们打开);System.out.println(—————-);smart.say(把他们关闭);}}六、组合模式 用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象用来表示部分以及整体层次结构抽象根节点定义系统各层次对象的共有方法和属性可以预先定义一些默认行为和属性树枝节点定义树枝节点的行为存储子节点组合树枝节点和叶子节点形成一个树形结构叶子节点叶子节点对象其下再无分支是系统层次遍历的最小单位分类根据抽象构建类的定义形式可以将组合模式分为透明组合模式和安全组合模式两种形式 1.透明组合模式抽象根节点角色中声明了所有用于管理成员对象的方法这样做的好处是确保所有的构件类都有相同的接口是组合模式的标准形式。透明模式的缺点是不够安全因为叶子对象和容器对象在本质上是有区别的叶子对象不可能有下一个层次的对象即不可能包含成员对象因此为其提供某些方法是没有意义的这在编译阶段不会出错但是在运行阶段如果调用这些方法可能会出错。 2.安全组合模式在抽象构件角色中没有声明任何用于管理成员对象的方法而是在树枝节点类中声明这些方法。缺点是不够透明因为叶子构件和容器构件具有不同的方法且容器构件中那些用于管理成员对象的方法没有在抽象构件中定义因此在客户端不能完全针对抽象编程因此有区别的对待叶子构件和容器构建。优点1.组合模式可以清楚地定义分层次的复杂对象表示对象的全部或部分层次他让客户端忽略了层次的差异方便对整个层次结构进行控制2.客户端可以一致的使用一个组合结构或其中单个对象不必关心处理的是单个对象还是整个组合简化了客户端代码3.在组合模式中增加新的树枝节点和叶子节点都很方便无须对现有类库进行任何修改4.组合模式为树形结构的面向对象实现提供了一种灵活的解决方案通过叶子节点和树枝节点的递归组合可以形成复杂的树形结构但对树形结构的控制却非常简单使用场景在出现树形结构的地方比如文件目录显示、多级目录呈现等/** 抽象根节点/ public abstract class MenuComponent {public String name;public int level;//层级//添加子菜单public void add(MenuComponent menuComponent){throw new UnsupportedOperationException();//默认抛出异常 菜单项不能添加子菜单}//移除子菜单public void remove(MenuComponent menuComponent){throw new UnsupportedOperationException();//默认抛出异常 菜单项不能移除子菜单}//获取指定的子菜单public MenuComponent getChild(int index){throw new UnsupportedOperationException();//默认抛出异常 菜单项不能获取子菜单}//获取菜单或者菜单项public String getName(){return name;}//打印菜单名称(包含子菜单和子菜单项)public abstract void print();}/** 树枝节点/ public class Menu extends MenuComponent{//菜单可以有多个子菜单或者子菜单项private ListMenuComponent list new ArrayList();public Menu(String name,int level){this.name name;this.level level;}Overridepublic void add(MenuComponent menuComponent) {list.add(menuComponent);}Overridepublic void remove(MenuComponent menuComponent) {list.remove(menuComponent);}Overridepublic MenuComponent getChild(int index) {return list.get(index);}Overridepublic void print() {//打印菜单名称for (int i 0;i level;i){System.out.print(-);}System.out.println(name -);//打印子菜单或者子菜单项名称for (MenuComponent menuComponent : list) {menuComponent.print();}} }/** 叶子节点/ public class MenuItem extends MenuComponent{public MenuItem(String name,int level){this.name name;this.level level;}Overridepublic void print() {//打印菜单项的名称for (int i 0;i level;i){System.out.print(-);}System.out.println(name);} }public class Test {public static void main(String[] args) {//创建菜单树MenuComponent menu1 new Menu(菜单管理,2);menu1.add(new MenuItem(页面访问,3));menu1.add(new MenuItem(展开菜单,3));menu1.add(new MenuItem(编辑菜单,3));menu1.add(new MenuItem(删除菜单,3));menu1.add(new MenuItem(新增菜单,3));MenuComponent menu2 new Menu(权限管理,2);menu2.add(new MenuItem(页面访问,3));menu2.add(new MenuItem(提交保存,3));MenuComponent menu3 new Menu(角色管理,2);menu3.add(new MenuItem(页面访问,3));menu3.add(new MenuItem(新增角色,3));menu3.add(new MenuItem(修改角色,3));//创建1级菜单MenuComponent component new Menu(系统管理,1);//将2级菜单添加到1级菜单中component.add(menu1);component.add(menu2);component.add(menu3);//打印菜单名称component.print();}}七、享元模式 运用共享技术来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象的数量、 避免大量相似对象的开销从而提高系统的资源利用率状态内部状态不会随着环境的改变而改变的可共享的部分外部状态指随环境改变而改变的不可以共享的部分。享元模式的实现要领就是区分应用中的两种状态结构抽象享元角色通常是一个接口或抽象类在抽象享元类中声明了具体享元类公共的方法这些方法可以向外界提供享元对象的内部数据(内部状态)同时也可以通过这些方法来设置外部数据(外部状态)具体享元角色它实现了抽象享元类称为享元对象在具体享元类中为内部状态提供了存储空间。通常可以结合单例模式来设计具体享元类为每一个具体享元类提供唯一的享元对象非享元角色并不是所有的抽象享元类的子类都需要被共享不能被共享的子类可设计为非共享具体享元类当需要一个非共享具体享元类的对象时可以直接通过实例化创建享元工厂角色负责创建和管理享元角色。当客户对象请求一个享元对象时享元工厂检查系统中是否存在符合要求的享元对象如果存在则提供给客户如果不存在的话则创建一个新的享元对象优点极大减少了内存中相似或者相同对象的数量节约系统资源提高系统性能享元模式中的外部状态相对独立且不影响内部状态缺点为了使对象可以共享需要将享元对象的部分状态外部化分离内部状态和外部状态使程序逻辑复杂使用场景一个系统有大量相同或者相似的对象造成内存的大量耗费对象的大部分状态都可以外部化可以将这些外部状态传入对象中/** 抽象享元角色/ public abstract class AbstractBox {//获取图形public abstract String getShape();//显示图形及颜色public void disPlay(String color){System.out.println(方块形状: getShape() , 颜色: color);}}/** 具体享元角色/ public class IBox extends AbstractBox{Overridepublic String getShape() {return I;} }/** 具体享元角色/ public class JBox extends AbstractBox{Overridepublic String getShape() {return J;} }/** 具体享元角色/ public class OBox extends AbstractBox{Overridepublic String getShape() {return O;} }/** 享元工厂角色* 设计为单例 采用饿汉式*/ public class BoxFactory {private MapString,AbstractBox map;private static BoxFactory factory new BoxFactory();private BoxFactory(){map new HashMap();map.put(I,new IBox());map.put(J,new JBox());map.put(O,new OBox());}public static BoxFactory getInstance(){return factory;}//根据名称获取图形对象public AbstractBox getShape(String name){if (!map.containsKey(name)){throw new NullPointerException(工厂中没有当前对象,请先创建该对象);}return map.get(name);}}public class Test {public static void main(String[] args) {AbstractBox box BoxFactory.getInstance().getShape(I);box.disPlay(黑色);}}