Java 继承最大的弱点和接口常用的模式

继承最大的弱点是打破封闭

继承关系会打破封闭,因此随意继承对象模型中的任意一个类是不安全的做法。建立对象模型时,应该先充分考虑软件系统中哪些地方需要扩展,为这些地方提供扩展点,也就是提供一些专门用于被继承的类

  1. 对这些类必须提供良好的文档说明,使得创建该类的子类的开发人员知道如何 正确安全地扩展它。对于那些 允许 子类覆盖的方法,应该详细地描述该方法的自用性,以及子类覆盖此方法可能带来的影响。所谓方法的自用性,是指在这个类中,有其他的方法会调用这个方法
  2. 尽可能地封闭父类的实现细节,也就是把代表实现细节的属性和方法定义为private类型。如果某些实现细节必须被子类访问,可以在父类中把包含这种实现细节的方法定义为protected类型。当子类调用父类的protected类型的方法,而不覆盖它时,可把这种protected类型的方法看做父类仅向子类但不对外部公开的接口。
  3. 把不允许子类覆盖的方法定义为final类型
  4. 父类的构造方法不允许调用可被子类覆盖的方法,因为如果这样做,可能会导致程序运行时出现未预料的错误。
  5. 如果某些类不是专门为了继承而设计,那么随意继承它是不安全的。因此可采取 以下两种措施来禁止继承:把类声明为final类型;把这个类的所有构造方法声明为private类型,然后通过一些静态方法来负责构造自身的实例。

接口常用的6种设计模式

(1),订制服务模式:设计精粒度的接口,每个接口代表相关的一组服务,通过继承来创建复合接口

  • 对服务精心分类,把相关的一组服务放在一个接口中,通过对接口的继承,可以派生出新的接口,针对使用者的需求提供选定的服务
  • 为了提高代码的可重用性,类的粒度也应该尽可能小,所以首先为精粒度的接口提供实现类

(2),适配器模式:当两个系统之间接口不匹配时,用适配器来转换接口。适配器模式的两种实现方式,因为继承关系只能把一个源接口转换为一个目标接口,因此 应该优先考虑用组合关系来实现适配器

1,继承的实现方式 
public class SourceImpl implements SourceIFC{

            @Override
            public int add(int a, int b) {
                    return a+b;
            }
    }
    public class TargetImpl extends SourceImpl {
            public int addOne(int a ){
                    return add(a,1);
            }
    }
2,组合实现方式
  public class TargetImpl implements TargetIFC{
            private SourceIFC source;
            public TargetImpl(SourceIFC source){
                    this.source=source;
            }
            public int add(int a,int b){return source.add(a,b)}
            public int addOne(int a){return source.add(a,1)}
    }

 

(3),默认适配器模式:为接口提供简单的默认实现。在java.awt.event 包中定义了许多事件监听接口,例如 WindowListener和MouseListener,它们分别用来响应用户发出的窗口事件和鼠标事件

//常用自定义的MyMouseListener监听器继承MouseAdaper类,实现单个鼠标事件方法
        public class MymouseListener extends MouseAdapter{
                public void mousePressed(mouseEvent e){
                        //处理按下鼠标事件
                        ……
                }
  }

(4),代理模式:为接口的实现类创建代理类,使用者通过代理类来获得实现类的服务。代理类与委托类有同样的接口,以下例子为了简化起见,假定一个代理人只会为一个出租人做代理。房屋出租人Renter对象、房产代理人Deputy对象、房屋租赁人Tenant对象,建立了Renter对象和Deputy对象的委托关系。

 

public interface RenterIFC{
                //是否同意按租赁人提出的价格出租房屋
                public boolean isAgree(double expectedRent);
                //收房租
                public void fetchRent(double rent);
        }

        public class Renter implements RenterIFC{

                //房屋租金最低价格
                private double rentDeadLine;
                //存款
                private  double money;
                
                public Renter(double rentDeadLine,double money){
                        this.rentDeadLine= rentDeadLine;
                        this.money = money;
                }

                public double getRentDeadLine() {
                        return rentDeadLine;
                }

                @Override
                public boolean isAgree(double expectedRent) {
                        //如果租赁人的期望价格比房屋租金最低价格多100元,则同意出租
                        return expectedRent-this.rentDeadLine>100;
                }

                @Override
                public void fetchRent(double rent) {
                        money+=rent;
                }
        }

        public class Deputy implements  RenterIFC{
                private Renter renter;
                public void registerRenter(Renter renter){
                        this.renter = renter;
                }


                @Override
                public boolean isAgree(double expectedRent) {
                        //如果租赁人的期望价格低于房屋租金最低价格,则不同意出租
                        if(expectedRent<renter.getRentDeadLine()) return false;

                        //否则请求出租人的意见
                        return renter.isAgree(expectedRent);


                }

                @Override
                public void fetchRent(double rent) {
                        renter.fetchRent(rent);
                }
        }

        public class HouseMarket{
                private static Set<RenterIFC> renters = new HashSet<RenterIFC>();
                public static void registerRenter(RenterIFC renter){
                        renters.add(renter);
                }
                public static RenterIFC findRenter(){
                        return  (RenterIFC)renters.iterator().next();
                }

        }

        public class Tenant{
                private double money;
                public Tenant(double money){
                        this.money = money;
                }
                public boolean rentHouse(double expectedRent){
                        //从房产市场找到一个代理人
                        RenterIFC renter = HouseMarket.findRenter();
                        //如果 代理人不同意预期租房价格,就拼命,否则 继续 执行
                        if(!renter.isAgree(expectedRent))return  false;
                        //从存款中取出预付租金
                        money -=expectedRent;
                        //把租金交给房产代理人
                        renter.fetchRent(expectedRent);
                        return  true;
                }
        }
        
        public class AppMain{
                public static void main(String[] args) throws  Exception{
                        //创建一个房屋出租人,房屋租金最低价格2000元,存款1万元
                        Renter renter = new Renter(2000,10000);
                        //创建一个房产代理人
                        Deputy deputy = new Deputy();
                        //房产代理人到房产市场登记
                        HouseMarket.registerRenter(deputy);
                        //建立房屋出租人和房产代理人的委托关系
                        deputy.registerRenter(renter);
                        
                        //创建一个房屋租凭人,存款为2万元
                        Tenant tenant = new Tenant(20000);
                        
                        //房屋租赁人试图租赁期望租金为1800元的房屋,遭到房产代理人拒绝
                        tenant.rentHouse(1800);
                        //房屋租赁人试图租赁期望租金为2000元房屋,租房成功
                        tenant.rentHouse(2300);
                        
                }
        }

 

(5),标识类模式:用接口来标识 一种没有任何行为的抽象类型,这种接口没有任何方法,仅代表一种抽象类型。在JDK中,有如下 两个典型的标识类型接口。

  • java.io.Serializable接口:实现该接口的类的实例可以被序列化。
  • java.io.Remote接口:实现该接口的类的实例可以作为远程对象。

(6),常量接口模式:在接口中定义静态常量,在其它类中通过import static 语句引入这些常量

public interface Myconstants{
          public static final Double MATH_PI=3.1415926;
          public static final Double MATH_E=2.71828;
  }

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值