模式-“里氏代换原则”

里氏代换原则是指拥有相同基类的两个子类,在使用子类A的地方(方法/属性)可以用子类

B来代替.对于面向接口编程,我只需要保证代码的行为不变;基类所有的方法子类必须全部

实现,换过来,子类的方法基类不一定都有;

假设:有一个基类Base;其子类是Concrete;那么method(Base b)的调用可以转换成

method(Concrete c);

策略模式:一般,我们把解决某个问题的方法称为一个"算法",而把解决一类问题的算法封装

成一个接口,那么实现算法的多种方式作为子类;在某个时候,在调用中我们使用算法A替换

算法B,这就是策略模式在里氏代换原则中的应用;

***************策略模式************************************

>准备一组算法,并将每一个封装起来使的他们可以互换.

Context

/**
 * 	@author Lean  @date:2014-10-17
 */
public class Context {

	public static Strategy strategy;

	public static void main(String[] args) {
		strategy=new ConcreteStrategyA();
		strategy.calculate();
	}

}

abstract class Strategy{

	public abstract void calculate();

}

class ConcreteStrategyA extends Strategy{

	@Override
	public void calculate() {
		System.out.println("ConcreteStrategyA is called !");
	}

}

class ConcreteStrategyB extends Strategy{

	@Override
	public void calculate() {
		System.out.println("ConcreteStrategyB is called !");
	}

IChoiceStrategy

/**
 * 		选择策略
 *
 * 	@author Lean  @date:2014-10-17
 */
public abstract class IChoiceStrategy {

	/**
	 * @return	返回列表名字
	 */
	public abstract String[] getNames();

	/**
	 * @return	返回对应码
	 */
	public abstract int getCode(String name);

}
/**
 * 	@author Lean  @date:2014-10-17
 */
public class SortChoiceStrategy extends IChoiceStrategy {

	private HashMap<String, Integer> mSortMap;
	public String name;

	public SortChoiceStrategy() {
		initSortMap();
	}

	private void initSortMap() {
		mSortMap=new HashMap<String, Integer>();
		mSortMap.put("最新上架", 0);
		mSortMap.put("销量最高", 1);
		mSortMap.put("价格最高", 2);
		mSortMap.put("价格最低", 3);
		name="最新上架";
	}

	@Override
	public String[] getNames() {
		Set<String> set=mSortMap.keySet();
		Object[] tempObj=set.toArray();
		String[] result=new String[tempObj.length];
		for (int i = 0; i < tempObj.length; i++) {
			result[i]=(String) tempObj[i];
		}
		return result;
	}

	@Override
	public int getCode(String name) {
		return mSortMap.get(name);
	}

}
/**
 * 	@author Lean  @date:2014-10-17
 */
public class StatusChoiceStrategy extends IChoiceStrategy {

	private HashMap<String, Integer> mStatusMap;
	public String name;

	public StatusChoiceStrategy() {
		initStatusMap();
	}

	private void initStatusMap() {
		mStatusMap=new HashMap<String, Integer>();
		mStatusMap.put("定制中", 1);
		mStatusMap.put("已完成", 2);
		name="定制中";
	}

	@Override
	public String[] getNames() {
		Set<String> set=mStatusMap.keySet();
		Object[] tempObj=set.toArray();
		String[] result=new String[tempObj.length];
		for (int i = 0; i < tempObj.length; i++) {
			result[i]=(String) tempObj[i];
		}
		return result;
	}

	@Override
	public int getCode(String name) {
		return mStatusMap.get(name);
	}

}

***********************************************************

代理模式:代理和被代理对象同样拥有一样的行为,我们把它封装成一个接口,那么,在被

代理对象被调用的地方都可以使用代理对象替换以隐藏实现细节;

***************代理模式************************************

假设一个场景,A想去买票,但A没时间,于是A托B到电影院帮他买票;

换成面向对象思维:假设有一个对象A,和一个新的对象C,现在C想使用对象A,而A暂时还

不符合C的要求,这时可以间接的使用B以达到使用A的目的,同时,B又可以对使用过程进行

拦截,如打印日志;(像这种利用中间层来达到目的的模式还有适配器模式)

/**
 * 	@author Lean  @date:2014-10-17
 */
public abstract class IPerson {

	public abstract void buyTicket();

}
/**
 * 	@author Lean  @date:2014-10-17
 */
public class RealSeePerson extends IPerson {

	@Override
	public void buyTicket() {
		System.out.println("RealSeePerson get the ticket !");
	}

}
/**
 * 	@author Lean  @date:2014-10-17
 */
public class BuyTicketPerson extends IPerson{

	public RealSeePerson target;

	private void preBuyTicket(){
		//TODO do th. before buy ticket
		target=new RealSeePerson();
	}

	@Override
	public void buyTicket() {
		preBuyTicket();
		if (target!=null) {
			target.buyTicket();
		}
		postBuyTicket();
	}

	public void postBuyTicket(){
		//TODO do th. after buy thicket
	}

}

>代理和被代理对象实现共同接口,代理对象被调用时调用被代理对象的委托;

动态代理实现监听:

/**
 * 	@author Lean  @date:2014-10-17
 */
public class VectorProxy implements InvocationHandler {

	private Object proxyobj;

	public VectorProxy(Object obj) {
		proxyobj=obj;
	}

	public static Object factor(Object obj){
		Class cls=obj.getClass();
		return Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),new VectorProxy(obj));
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		System.out.println("method:"+method.getName());
		if (args!=null) {
			for (int i = 0; i < args.length; i++) {
				System.out.println(args[i]+"");
			}
		}
		//反射调用
		Object obj=method.invoke(proxyobj, args);
		System.out.println("*********");
		return obj;
	}

	public static void main(String[] args) {
		List v=null;
		//返回代理对象,并调用代理对象的add方法
		v=(List) factor(new Vector(10));
		v.add("New");
	}

}

***********************************************************

合成模式:上面两中模式都是里氏代换原则在方法方面的应用.合成模式使用树结果描述

整体和部分的关系,因为单纯元素和复合元素同样实现抽象,那么在抽象使用的地方,

都可以这2种元素替代;

***************合成模式************************************

合成模式分为透明式和安全式

透明:指抽象接口声明了枝叶所有的所有接口方法,在叶子类中,对该方法进行空实现;

/**
 * 	@author Lean  @date:2014-10-20
 */
public interface Component {

	void sampleOperation();

	Composite getComposite();

	void add(Component component);

	void remove(Component component);

	Enumeration<Component> components();

}
/**
 * 	@author Lean  @date:2014-10-20
 */
public class Composite implements Component {

	private Vector<Component> componentVector=new Vector<Component>();

	@Override
	public Composite getComposite() {
		return this;
	}

	@Override
	public void sampleOperation() {
		Enumeration<Component> enumeration=components();
		while (enumeration.hasMoreElements()) {
			Component component = (Component) enumeration.nextElement();
			component.sampleOperation();
		}
	}

	@Override
	public void add(Component component) {
		componentVector.addElement(component);
	}

	@Override
	public void remove(Component component) {
		componentVector.removeElement(component);
	}

	@Override
	public Enumeration<Component> components() {
		return componentVector.elements();
	}

}
/**
 * 	@author Lean  @date:2014-10-20
 */
public class Leaf implements Component {

	@Override
	public Composite getComposite() {
		return null;
	}

	@Override
	public void sampleOperation() {
		System.out.println(" call leaf here !");
	}

	@Override
	public void add(Component component) {

	}

	@Override
	public void remove(Component component) {

	}

	@Override
	public Enumeration<Component> components() {
		return null;
	}

}

安全:指抽象接口只声明叶子所有的方法,树枝类除了继承还包括了自己的管理叶子类方法;典型应用:Android的View,ViewGroup

/**
 * 	@author Lean  @date:2014-10-20
 */
public interface Component {

	Composite getComposite();

	void sampleOperation();

}
/**
 * 	@author Lean  @date:2014-10-20
 */
public class Composite implements Component {

	private Vector componentVector=new Vector();

	@Override
	public void sampleOperation() {
		Enumeration enumeration=components();
		while (enumeration.hasMoreElements()) {
			((Component) enumeration.nextElement()).sampleOperation();
		}
	}

	@Override
	public Composite getComposite() {
		return this;
	}

	public Enumeration components(){
		return componentVector.elements();
	}

	public void add(Component component){
		componentVector.addElement(component);
	}

	public void remove(Component component){
		componentVector.removeElement(component);
	}

}
/**
 * 	@author Lean  @date:2014-10-20
 */
public class Leaf implements Component {

	@Override
	public Composite getComposite() {
		return null;
	}

	@Override
	public void sampleOperation() {
		System.out.println("leaf is called !");
	}

}

因为枝叶基本继承了抽象类,在一个只支持抽象方法的类中,可以替换成另一个枝叶;比如在安全模式中,叶子类可以替换成枝/叶类;在透明模式中可以互相替换;这就符合了里氏代换原则;

***********************************************************

时间: 2024-11-19 21:51:12

模式-“里氏代换原则”的相关文章

里氏代换原则等

<Java与模式>读书笔记. 里氏代换原则 里氏代换原则(LSP)简言之就是基类的属性方法一定是适应于子类的,反之则不然. 在编译期,Java编译器就会检查程序是否是符合里氏代换原则,不符合就不能通过.违反里氏代换原则的一个例子就是子类试图将基类中的public方法覆盖为private方法,是编译不过的,子类中接口的使用范围只能更广. Java编译器检查程序是否是符合里氏代换原则是有限的,实现层次和逻辑层次是无法判断的. Java API中也有违反里氏代换原则的例子,Properties继承自

设计模式中的里氏代换原则

设计模式中的里氏代换原则 Table of Contents 1 里氏代换原则 2 模式中的里氏代换原则 2.1 策略模代 2.2 合成模式 2.3 代理模式 3 如何继承 3.1 不要从具体类继承 3.2 避免错误继承 1 里氏代换原则 从开-闭原则中可以看出来面向对象的重要原则是创建抽象化,并从抽象化导出具体化.具 体化可以给出不同的版本,每一版本都给出不同的实现.里氏代换原则从另一个侧面描述 抽象化和具体化,里氏代换原则表明:一个软件如果使用的是一个基类的话,那么一定适 用于其子类,而且它

模式-“里氏替换原则”

里氏替换原则是,同组的有类的两个子类,在使用子类A这个地方(方法/属性)您可以使用子类 B代替.对于面向接口编程,我只需要确保同样的行为代码;基类的所有子类必须全部 实现,换过来,子类的方法基类不一定都有; 如果:有一个基类Base;其子类是Concrete;那么method(Base b)的调用能够转换成 method(Concrete c); 策略模式:一般,我们把解决某个问题的方法称为一个"算法",而把解决一类问题的算法封装 成一个接口,那么实现算法的多种方式作为子类;在某个时候

设计模式之里氏代换原则(LSP)

里氏代换原则(Liskov Substitution Principle, LSP) 1 什么是里氏代换原则 里氏代换原则是由麻省理工学院(MIT)计算机科学实验室的Liskov女士,在1987年的OOPSLA大会上发表的一篇文章<Data Abstraction and Hierarchy>里面提出来的,主要阐述了有关继承的一些原则,也就是什么时候应该使用继承,什么时候不应该使用继承,以及其中的蕴涵的原理.2002年,我们前面单一职责原则中提到的软件工程大师Robert C. Martin,

设计模式 之 里氏代换原则 (Liskov&#39;s Substitution Principle)

Motivation 动机 All the time we design a program module and we create some class hierarchies. Then we extend some classes creating some derived classes. 一直以来,我们设计程序模块,并且建立类的层次关系,然后扩展类来创建派生类. We must make sure that the new derived classes just extend wi

设计原则之里氏代换原则

设计原则之里氏代换原则 substitute  = replace 替换 sub 下 st石头 i我  tu土 te特别 我用石头替换下土,造了特比坚固的房子 hierarchy  ['harɑk] = level 等级 hi海豹  er儿子  ar are是  ch成龙 海豹儿子的雷霆战机等级是比成龙高 derive [di'raiv]  起源,派生 de德国  rive river河 德国的莱茵河起源于阿尔卑斯山 动机:         当我们创建类的层级(继承),我们继承一些类,创建一些派

里氏代换原则

若对于每一个类型S的对象o1,都存在一个类型T的对象o2,使得在所有针对T编写的程序P中,用o1替换o2后,程序P的行为功能不变,则S是T的子类型. What is wanted here is something like the following substitution property: If for each object o1 of type S there is an object o2 of type T such that for all programs P defined

面向对象设计原则之里氏代换原则

http://blog.csdn.net/lovelion/article/details/7540445 里氏代换原则是实现开闭原则的重要方式之一,由于使用基类对象的地方都可以使用子类对象,因此在程序中尽量使用基类类型来对对象进行定义,而在运行时再确定其子类类型,用子类对象来替换父类对象. 在使用里氏代换原则时需要注意如下几个问题: (1)子类的所有方法必须在父类中声明,或子类必须实现父类中声明的所有方法.根据里氏代换原则,为了保证系统的扩展性,在程序中通常使用父类来进行定义,如果一个方法只存

西游记之设计模式原则——里氏代换原则

里氏代换原则 --子类能替换父类 1 package lishidaihuan; 2 3 class TangSeng { 4 public void QuJing() { 5 System.out.println("施主,贫僧自东土大唐而来,去往西天拜佛求经!"); 6 } 7 } 8 9 class TuDi extends TangSeng { 10 public void QuJing() { 11 super.QuJing(); 12 System.out.println(&