浅谈装饰模式
装饰与继承的区别:
装饰:基于已有的功能,并提供加强功能,装饰类通常会通过构造方法接收被装饰的对象。并基于被装饰的对象的功能,提供更强的功能。相对于继承来说装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。英文叫:Decorator
继承:因为要扩展某个功能,就得继承父类,然后覆盖重写,导致这个体系更加臃肿,并且内存占用高。
一般情况下,其实接口也可以当做一种抽象类来看待,也就是说父类对象也可以是接口,如果一个类A实现了一个接口T,当我们在声明实例:T t =new A();时,t看起来是一个T,本质上是一个A,这也是多态的一种!
验证一下,首先先创建一个接口a:
public class test { interface a{ void fun(); } class b implements a{ public void fun() { System.out.println("这个实现接口类!"); } } class c extends b{ public void fun(){ System.out.println("这是实现接口类的子类!!"); } } public static void main(String[] args) { a dd = new test().new c(); dd.fun(); } }
运行:
例1:
摘自CSDN的一位大神的例子,看这个程序只要多态的功能理清楚也就明白了,说白了装饰模式无非就是多态与构造方法的灵活运用罢了:
public class decorateMode{ //定义被装饰者 public interface Human { public void wearClothes(); public void walkToWhere(); } //定义装饰者 public abstract class Decorator implements Human { private Human human; public Decorator(Human human) { this.human = human; } public void wearClothes() { human.wearClothes(); } public void walkToWhere() { human.walkToWhere(); } } //下面定义三种装饰,这是第一个,第二个第三个功能依次细化,即装饰者的功能越来越多 public class Decorator_zero extends Decorator { public Decorator_zero(Human human) { super(human); } public void goHome() { System.out.println("进房子。。"); } public void findMap() { System.out.println("书房找找Map。。"); } public void wearClothes() { // TODO Auto-generated method stub super.wearClothes(); goHome(); } public void walkToWhere() { // TODO Auto-generated method stub super.walkToWhere(); findMap(); } } public class Decorator_first extends Decorator { public Decorator_first(Human human) { super(human); } public void goClothespress() { System.out.println("去衣柜找找看。。"); } public void findPlaceOnMap() { System.out.println("在Map上找找。。"); } public void wearClothes() { // TODO Auto-generated method stub super.wearClothes(); goClothespress(); } public void walkToWhere() { // TODO Auto-generated method stub super.walkToWhere(); findPlaceOnMap(); } } public class Decorator_two extends Decorator { public Decorator_two(Human human) { super(human); } public void findClothes() { System.out.println("找到一件D&G。。"); } public void findTheTarget() { System.out.println("在Map上找到神秘花园和城堡。。"); } public void wearClothes() { // TODO Auto-generated method stub super.wearClothes(); findClothes(); } public void walkToWhere() { // TODO Auto-generated method stub super.walkToWhere(); findTheTarget(); } } //定义被装饰者,被装饰者初始状态有些自己的装饰 public class Person implements Human { public void wearClothes() { // TODO Auto-generated method stub System.out.println("穿什么呢。。"); } public void walkToWhere() { // TODO Auto-generated method stub System.out.println("去哪里呢。。"); } } //测试类,看一下你就会发现,跟java的I/O操作有多么相似 public static void main(String[] args) { decorateMode decorateMode=new decorateMode(); Human person =decorateMode. new Person(); Decorator decorator = decorateMode.new Decorator_two(decorateMode.new Decorator_first( decorateMode.new Decorator_zero(person))); decorator.wearClothes(); decorator.walkToWhere(); } }
运行结果:
例2:
读取文件的行内容,并给每行前加上行数、行后加上分号
package com.beiwo.Io; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.Reader; /* BufferedReader : 拓展FileReader的功能。 需求1 :实现通过readLine读取代码 ,每一行加上一个行号。 需求2 :实现通过readLine读取代码 ,每一行加上一个分号。 需求3 :实现通过readLine读取代码 ,每一行加上一个引号。 //========================================================= 需求4 :实现通过readLine读取代码 ,每一行加上一个引号 + 行号。 需求5 :实现通过readLine读取代码 ,每一行加上一个分号 + 行号。 需求6 :实现通过readLine读取代码 ,每一行加上一个分号 + 引号。 需求7 :实现通过readLine读取代码 ,每一行加上一个分号 + 引号 + 行号。 如果用继承: 好处:代码结构和清晰容易理解 缺点:继承体系会很庞大。实现七个需求就得创建七个子类 装饰者模式 : 增强一个类的功能还可以让装饰者类之间互相装饰。 */ //添加行号 class BufferedReaderLineNum extends BufferedReader{ //定义一个对象来接收传进来的对象 BufferedReader bufferedReader; int count = 1; //子类继承父类会默认调用父类的无参构造方法 public BufferedReaderLineNum (BufferedReader in) { super(in); this.bufferedReader = in; } //复写readLine方法 @Override public String readLine() throws IOException { // TODO Auto-generated method stub //调用父类的readLine String content = bufferedReader.readLine(); //给内容田间一个行号 if(content == null){ return null; } content = count+" "+content; count++; return content; } } //添加分号的 class BufferedReaderLineSemi extends BufferedReader{ //定义一个对象来接收传进来的对象 BufferedReader bufferedReader; //子类继承父类会默认调用父类的无参构造方法 public BufferedReaderLineSemi (BufferedReader in) { super(in); this.bufferedReader = in; } //复写(重写)readLine方法 @Override public String readLine() throws IOException { // TODO Auto-generated method stub //调用父类的readLine String content = bufferedReader.readLine(); //给内容田间一个行号 if(content == null){//表示数据已经读完 return null; } return content+";"; } } public class Demo1 { /** * @param args * @throws IOException */ public static void main(String[] args) throws IOException { // TODO Auto-generated method stub testLineNum(); } public static void testLineNum () throws IOException{ //1.开启一个通道,并且带一个文件路径 FileReader reader = new FileReader("这里填上文件路径如:C:\\a.java"); //创建缓冲流 BufferedReader bufferedReader = new BufferedReader(reader); //2.创建一个带分号的缓冲流 BufferedReaderLineSemi lineSemi = new BufferedReaderLineSemi(bufferedReader); //创建一个缓冲流 ,带行号加分号 BufferedReaderLineNum lineNum = new BufferedReaderLineNum(lineSemi); //3.开始读取数据 String content = null; while((content = lineNum.readLine())!=null){ System.out.println(content); } //4.关闭资源 lineNum.close(); } }
效果:
相关推荐
FlySky 2020-09-29
chenzulong 2020-08-16
Freeman00 2020-05-01
codercheng 2020-04-09
JakobHu 2020-02-10
xilove0 2020-01-10
Ayiayi00 2019-11-16
88236435 2019-07-01
AdrianAndroid 2016-12-24
QiaoranC 2019-06-29
changcongying 2019-06-28
newtrekWang 2019-06-27
t0ckh 2011-08-16
liuxiaohua 2019-06-27
paopao00 2019-06-27
homesmile 2015-03-30
zhangbeizhen 2019-06-27
Elixir 2019-06-21