您的位置:首页 > 职场人生

黑马程序员----java设计模式之装饰设计模式和享元设计模式

2014-03-05 11:42 411 查看
------- android培训java培训、期待与您交流!
----------    

 * 装饰设计模式:当想要对已有的对象进行功能加强时,

     * 可以自定义类,将已有的对象传入,基于已存在的功能,提供功能加强。

     * 那么自定义类称之为装饰类。

     * 

     * 装饰类特点:通常通过构造方法将被装饰的对象传入,并基于装饰对象已有的功能进行加强

     * 例如:IO流中fileReader对象提供了read方法读取数据,

     * 但它有个装饰类bufferedReader 提供了readLine()方法一行一行读取数据,在filereader对象功能上提供更强的读取数据方法,所以称之为装饰设计模式。

public class PersonDemo {

/**
* @author Administrator
*/
public static void main(String[] args) {
Person p=new Person();
supperPerson sPerson=newsupperPerson(p);
sPerson.supperChifan();

}

}

class Person{

public void chifan(){
System.out.println("吃饭吃饭");
}

}
//自定义类,对被装饰类的对象功能进行加强
class supperPerson{

private Person p;//定义被装饰对象
//通过构造方法将被装饰的对象传入
public supperPerson(Person p){
this.p=p;
}
//对被装饰对象功能进行加强
public void supperChifan(){
System.out.println("喝点小酒");
p.chifan();
System.out.println("那就开始吃饭吧");
}

}
继承与装饰模式

    继承:是使用已存在的类的定义作为基础建立新的类。新类可以增加数据或新的功能,也可以使用父类的方法,但不能选择性的继承父类。优点:提高了代码的重用行,降低了项目开发周期。

      装饰模式:对已有的对象的功能进行加强。特点:通常通过构造函数将被增强的对象传入,并基于被装饰(增强对象)已有的功能加强。

      myReader--------专门用于读取数据的类

          |---MyTextReader

               |--MyBufferTextReader

         |---MyMediaReader

               |--MyBufferMediaReader

 

 上面这种体系说明:myReader下有MyTextReader,MyMediaReader两个子类。MyTextReader下有MyBufferTextReader子类,提供更高效率读取数据的子类,同理MyMediaReader也是一样。因此我们发现如果myreader下有多个子类的话,那么每个子类下都有提供更高效率读取数据的子类。所以这样显得代码有些臃肿。

     于是我们把所有提高读取数据效率的类全部抽取出来,MuBufferReader。

     classMyBufferReader{

        private  MyTextReader  text;

        private  MyMediaReader  media;

        .............

         MyBufferReader(MyTextReader text){}

         MyBufferReader(MyMediaReader media){}

.............

     }

   

   上面这种我们也发现如果存在多个读取数据的类,那么这里将会有多个构造函数将被增加的对象传入.因此发现这样扩展性极差。

   如何提高扩展性呢?? --------找到参数的共同类型,通过多态的形式,可以提高扩展性。

   class MyBufferReaderextends MyReader{

        private  MyReader  r;

        

         MyBufferReader(MyReader r){}//这就是运用装饰设计模式特征,将被增强的对象通过构造函数传入。

 

     }

因为MyTextReader  MyMediaReader 都属于myReader的子类,所以现在结构体系如下:

  

    myReader--------专门用于读取数据的类

         |---MyTextReader

         |---MyMediaReader

         |---MyBufferReader 

总结:装饰模式比继承更灵活,避免了继承体系的臃肿。而且降低了类与类之间的关系。装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提高了更强的功能,所以装饰类和被装饰类属于一个体系中。

 

 享元设计模式:flyweight

 概念:如果很多很小的对象他们有很多相同的东西,那么就可以把他们变成一个对象。还有一些不同的东西,可以作为方法的属性作外部参数的形式传入。称之为外部状态。相同的属性称之为内部状态。

 

 也就是说:也就是说在一个系统中如果有多个相同的对象,那么只共享一份就可以了,不必每个都去实例化一个对象。比如说(这里引用GOF书中的例子)一个文本系统,每个字母定一个对象,那么大小写字母一共就是52个,那么就要定义52个对象。如果有一个1M的文本,那么字母是何其的多,如果每个字母都定义一个对象那么内存早就爆了。那么如果要是每个字母都共享一个对象,那么就大大节约了资源。

 

比如说,一个咖啡店有几种口味的咖啡(拿铁、摩卡、卡布奇诺等等),如果这家店接到分订单要几十杯咖啡。那么显然咖啡的口味就可以设置成共享的,而不必为每一杯单独生成。代码实现如下:

importjava.util.*;
public abstractclass Order {
// 执行卖出动作
public abstract void sell();
}
public classFlavorOrder extends Order {
public String flavor;
// 获取咖啡口味
public FlavorOrder(String flavor) {
this.flavor = flavor;
}
@Override
public void sell() {
// TODO Auto-generated method stub
System.out.println("卖出一份" + flavor + "的咖啡。");
}
}
public classFlavorFactory {
private Map<String, Order> flavorPool = new HashMap<String,Order>();
// 静态工厂,负责生成订单对象
private static FlavorFactory flavorFactory = new FlavorFactory();
privateFlavorFactory() {
}
public staticFlavorFactory getInstance() {
return flavorFactory;
}
public OrdergetOrder(String flavor) {
Order order = null;
if(flavorPool.containsKey(flavor)) {// 如果此映射包含指定键的映射关系,则返回 true
order = flavorPool.get(flavor);
}else {
order = new FlavorOrder(flavor);
flavorPool.put(flavor, order);
}
return order;
}
public intgetTotalFlavorsMade() {
return flavorPool.size();
}
}
public classClient {
// 客户下的订单
private static List<Order> orders = new ArrayList<Order>();
// 订单对象生成工厂
private static FlavorFactory flavorFactory;
// 增加订单
private static void takeOrders(String flavor) {
orders.add(flavorFactory.getOrder(flavor));
}
public staticvoid main(String[] args) {
// 订单生成工厂
flavorFactory = FlavorFactory.getInstance();
//增加订单
takeOrders("摩卡");
takeOrders("卡布奇诺");
takeOrders("香草星冰乐");
takeOrders("香草星冰乐");
takeOrders("拿铁");
takeOrders("卡布奇诺");
takeOrders("拿铁");
takeOrders("卡布奇诺");
takeOrders("摩卡");
takeOrders("香草星冰乐");
takeOrders("卡布奇诺");
takeOrders("摩卡");
takeOrders("香草星冰乐");
takeOrders("拿铁");
takeOr
4000
ders("拿铁");
//卖咖啡
for (Order order : orders) {
order.sell();
}
//打印生成的订单java对象数量
System.out.println("\n客户一共买了 " + orders.size() + " 杯咖啡! ");
//打印生成的订单java对象数量
System.out.println("共生成了 " +flavorFactory.getTotalFlavorsMade()
+ " 个 FlavorOrder java对象! ");
}
}打印结果:
卖出一份摩卡的咖啡。

卖出一份卡布奇诺的咖啡。

卖出一份香草星冰乐的咖啡。

卖出一份香草星冰乐的咖啡。

卖出一份拿铁的咖啡。

卖出一份卡布奇诺的咖啡。

卖出一份拿铁的咖啡。

卖出一份卡布奇诺的咖啡。

卖出一份摩卡的咖啡。

卖出一份香草星冰乐的咖啡。

卖出一份卡布奇诺的咖啡。

卖出一份摩卡的咖啡。

卖出一份香草星冰乐的咖啡。

卖出一份拿铁的咖啡。

卖出一份拿铁的咖啡。

客户一共买了 15 杯咖啡!

共生成了 4 个 FlavorOrderjava对象!

正如输入结果对比所示,把口味共享极大减少了对象数目,减小了内存消耗。

------- android培训java培训、期待与您交流!
---------- 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐