189 8069 5689

java小黄鸭代码 程序小黄鸭

软件设计模式鸭子模拟器

假设我们需要设计出各种各样的鸭子,一边游泳戏水, 一边呱呱叫。很明显这时我们需要设计了一个鸭子超类(Superclass),并让各种鸭子继承此超类。

创新新互联,凭借10余年的做网站、网站建设经验,本着真心·诚心服务的企业理念服务于成都中小企业设计网站有上千多家案例。做网站建设,选创新互联。

public abstract class Duck {

public void Swim() {

//会游泳

}

public abstract display();//各种外观不一样,所以为抽象

public void Quack() {

//会叫

}

}

每一只鸭子就继承Duck类

public class MallardDuck extends Duck {

public void display() {

// 外观是绿色的

}

}

public class RedheadDuck extends Duck{

public void display(){

// 外观是红色的

}

}

好了,我们完成这些后,但是发现我们需要有一些鸭子是会飞的,应该怎么修改呢?

也许你要说这很简单,在Duck类里面直接加入一个fly()方法,不就可以了。

public abstract class Duck {

public void Swim() {

//会游泳

}

public abstract display();//各种外观不一样,所以为抽象

public void Quack() {

//会叫

}

public void fly(){

//会飞

}

}

这时你会发现所有的鸭子都变成了会飞的,很明显这是不对了,例如橡皮鸭显然就不是了。

你也许想到了另一种方法,在会飞的鸭子类里才添加该方法不就可以了嘛,

public class MallardDuck extend Duck{

public void display(){

// 外观是绿色的

}

public void fly(){

//会飞

}

}

这个方法看起来是很不错,可是有很多种鸭子都会飞的时候,代码的复用性很明显是不够好的,你不得不在

每一个会飞的鸭子类里去写上同一个fly()方法,这可不是个好主意.

可能你又想到另一个方法:采用继承和覆盖,在Duck类里实现fly()方法,在子类里如果不会飞的就覆盖它

public abstract class Duck {

public void Swim() {

//会游泳

}

public abstract display();//各种外观不一样,所以为抽象

public void Quack(){

//会叫

}

public void fly(){

//会飞

}

}

//橡皮鸭吱吱叫,不会飞

public class RubberDuck extend Duck{

public void quack(){

//覆盖成吱吱叫

}

public void display{

//外观是橡皮鸭

}

public void fly{

//什么也不做

}

}

这样我们真实现了确实能飞的鸭子才可以飞起来了,看起来主意不错!问题到这儿似乎得到了解决

但我们现在有了一种新的鸭子,诱铒鸭(不会飞也不会叫),看来需要这样来写

public class DecoyDuck extend Duck{

public void quack(){

//覆盖,变成什么也不做

}

public void display(){

//诱饵鸭

}

public void fly(){

//覆盖,变成什么也不做

}

}

每当有新的鸭子子类出现或者鸭子新的特性出现,就不得不被迫在Duck类里添加并在所有子类里检查可能需要覆盖fly()和quark()...这简直是无穷尽的恶梦。所以,我们需要一个更清晰的方法,让某些(而不是全部)鸭子类型可飞或可叫。让鸭子的特性能有更好的扩展性。

用一下接口的方式把fly()取出来,放进一个Flyable接口中,这样只有会飞的鸭子才实现这个接口,当然我们也可以照此来设计一个Quackbable接口,因为不是所有的鸭子都会叫,也只让会叫的鸭子才去实现这个接口.

但这个方法和上面提到的在子类里去实现fly一样笨,如果几十种都可以飞,你得在几十个鸭子里去写上一样的fly(),如果一旦这个fly有所变更,你将不得不找到这几十个鸭子去一个一个改它们的fly()方法。

因为改变鸭子的行为会影响所有种类的鸭子,而这并不恰当。Flyable与Quackable接口一开始似乎还挺不错, 解决了问题( 只有会飞的鸭子才继承Flyable) , 但是Java的接口不具有实现代码, 所以继承接口无法达到代码的复用。这意味着:无论何时你需要修改某个行为,你必须得往下追踪并修改每一个定义此行为的类。

策略模式的第一原则:找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。 好吧,回头看一下这个Duck类,就我们目前所知,除了fly()和quack()的问题之外,Duck类还算一切正常,主要是鸭子的行为总是可能变化的,让我们头痛就在于这些行为的变化,那我们就把这些行为独立出来。

为了要把这两个行为从Duck 类中分开, 我们将把它们自Duck 类中取出,建立一组新类代表每个行为。我们建立两组类(完全远离Duck类),一个是「fly」相关的,一个是「quack」相关的,每一组类将实现各自 的动作。比方说,我们可能有一个类实现「呱呱叫」,另一个类实现「吱吱叫」,另一个类实现「安静」。我们利用接口代表每组行为,比方说, FlyBehavior来代表飞的行为,QuackBehavior代表叫的行为,而让每一种行为具体类来实现该行为接口。

在此,我们有两个接口,FlyBehavior和QuackBehavior,还有它们对应的类,负责实现具体的行为:

public interface FlyBehavior {

public void fly();

}

public class FlyWithWings implements FlyBehavior{

public void fly{}{

//实现鸭子飞行

}

}

public class FlyNoWay implements FlyBehavior{

public void fly{}{

//什么也不做,不会飞

}

}

public interface QuackBehavior{

public void quack();

}

public class Quack implements QuackBehavior{

public void quack(){

//实现鸭子呱呱叫

}

}

public class Squeak implements QuackBehavior{

public void quack(){

//实现鸭子吱吱叫

}

}

public class MuteQuack implements QuackBehavior{

public void quack(){

//什么也不做,不会叫

}

}

实际上这样的设计,我们已经可以让飞行和呱呱叫的动作被其他的对象复用,因为这些行为已经与鸭子类无关了。如果我们新增一些行为,也不会影响到既有的行为类,也不会影响有已经使用到飞行行为的鸭子类。

好了,我们设计好鸭子的易于变化的行为部分后,该到了整合鸭子行为的时候了。

这时我们该想到策略模式的另一个原则了:

针对接口编程,而不是针对实现编程。

首先, 在鸭子中加入两个实例变量,分别为「flyBehavior」与「quackBehavior」,声明为接口类型( 而不是具体类实现类型), 每个变量会利用多态的方式在运行时引用正确的行为类型( 例如:FlyWithWings 、Squeak...等)。我们也必须将Duck类与其所有子类中的fly()与quack()移除,因为这些行为已经被搬移到FlyBehavior与 Quackehavior类中了,用performFly()和performQuack()取代Duck类中的fly()与quack()。

public abstract class Duck(){

FlyBehavior flyBehavior;

QuackBehavior quackBehavior;

public void swim(){

//会游泳

}

public abstract void display();//各种外观不一样,所以为抽象

public void performQuack(){

quackBehavior.quack();

}

public void performFly(){

flyBehavior.fly();

}

}

很容易,是吧?想进行呱呱叫的动作,Duck对象只要叫quackBehavior对象

去呱呱叫就可以了。在这部分的代码中,我们不在乎QuackBehavior 接口的对象到底是什么,我们只关心该对象

知道如何进行呱呱叫就够了。

好吧! 现在来关心如何设定flyBehavior 与quackBehavior的实例变量。

看看MallardDuck类:

public class MallardDuck extends Duck {

public MallardDuck() {

\\绿头鸭使用Quack类处理呱呱叫,所以当performQuack() 被调用,就把责任委托给Quack对象进行真正的呱呱叫。

quackBehavior = new Quack();

\\使用FlyWithWings作为其FlyBehavior类型。

flyBehavior = new FlyWithWings();

}

}

所以,绿头鸭会真的『呱呱叫』,而不是『吱吱叫』,或『叫不出声』。这是怎么办到的?当MallardDuck实例化时,它的构造器会

把继承来的quackBehavior实例变量初始化成Quack类型的新实例(Quack是QuackBehavior的具体实现类)。同样的处理方式也可以用在飞行行为上: MallardDuck 的构造器将flyBehavior 实例变量初始化成FlyWithWings 类型的实例(

FlyWithWings是FlyBehavior的具体实现类)。

输入下面的Duck类(Duck.java) 以及MallardDuck 类MallardDuck.java),并编译之。

public abstract class Duck {

//为行为接口类型声明两个引用变量, 所有鸭子子类(在同一个packge)都继承它们。

FlyBehavior flyBehavior;

QuackBehavior quackBehavior;

public Duck() {

}

public abstract void display();

public void performFly() {

flyBehavior.fly();//委托给行为类

}

public void performQuack() {

quackBehavior.quack();//委托给行为类

}

public void swim() {

System.out.println("All ducksfloat, even decoys!");

}

}

public class MallardDuck extends Duck {

public MallardDuck() {

quackBehavior = newQuack();

flyBehavior = newFlyWithWings();

}

public void display() {

System.out.println("I’m a real Mallard duck");

}

}

输入FlyBehavior接口(FlyBehavior.java)与两个行为实现类(FlyWithWings.java与FlyNoWay.java),并编译之。

public interface FlyBehavior {//所有飞行行为类必须实现的接口

public void fly();

}

public class FlyWithWings implements FlyBehavior {//这是飞行行为的实现, 给「真会」飞的鸭子用 .. .

public void fly() {

System.out.println("I’m flying!!");

}

}

public class FlyNoWay implements FlyBehavior {//这是飞行行为的实现, 给「不会」飞的鸭子用( 包括橡皮鸭和诱饵鸭)

public void fly() {

System.out.println("I can’t fly");

}

}

输入QuackBehavior接口(QuackBehavior.java)及其三个实现类(Quack.java、MuteQuack.java、Squeak.java),并编译之。

public interface QuackBehavior {

public void quack();

}

public class Quack implements QuackBehavior {

public void quack() {

System.out.println(“Quack”);

}

}

public class MuteQuack implements QuackBehavior {

public void quack() {

System.out.println(“ Silence ”);

}

}

public class Squeak implements QuackBehavior {

public void quack() {

System.out.println(“Squeak”);

}

}

输入并编译测试类(MiniDuckSimulator.java)

public class MiniDuckSimulator {

public static void main(String[] args) {

Duck mallard = new MallardDuck();

mallard.display();

//这会调用MallardDuck继承来的performQuack() ,进而委托给该对象的QuackBehavior对象处理。(也就是说,调用继承来的quackBehavior的quack())

mallard.performQuack();

//至于performFly() ,也是一样的道理。

mallard.performFly();

}

}

运行结果:

I’m a real Mallard duck

Quack

I’m flying!!

虽然我们把行为设定成具体的类(通过实例化类似Quack 或FlyWithWings的行为类, 并指定到行为引

用变量中),但是还是可以在运行时轻易地改变该行为。

所以,目前的作法还是很有弹性的,只是初始化实例变量的作法不够弹性罢了。

我们希望一切能有弹性,毕竟,正是因为一开始的设计的鸭子行为没有弹性,才让我们走到现在这条路。

我们还想能够「指定」行为到鸭子的实例, 比方说, 想要产生绿头鸭实例,并指定特定「类型」的飞行

行为给它。干脆顺便让鸭子的行为可以动态地改变好了。换句话说,我们应该在鸭子类中包含设定行为的方法。

因为quackBehavior实例变量是一个接口类型,所以我们是能够在运行时,透过多态动态地指定不同的QuickBehavior实现类给它。

我们在鸭子子类透过设定方法(settermethod)设定鸭子的行为,而不是在鸭子的构造器内实例化。

在Duck类中,加入两个新方法:从此以后,我们可以「随时」调用这两个方法改变鸭子的行为。

public strate class Duck(){

FlyBehavior flyBehavior;

QuackBehavior quackBehavior;

public void setFlyBehavior(FlyBehavior fb) {

flyBehavior = fb;

}

public void setQuackBehavior(QuackBehavior qb) {

quackBehavior = qb;

}

}

好了,让我们再制造一个新的鸭子类型:模型鸭(ModelDuck.java)

public class ModelDuck extends Duck {

public ModelDuck() {

flyBehavior = new FlyNoWay();//初始状态,我们的模型鸭是不会飞的。

quackBehavior = new Quack();//初始状态,我们的模型鸭是可以叫的.

}

public void display() {

System.out.println("I’m a modelduck");

}

}

建立一个新的FlyBehavior类型(FlyRocketPowered.java)

public class FlyRocketPowered implements FlyBehavior {

// 我们建立一个利用火箭动力的飞行行为。

public void fly() {

System.out.println("I’m flying with arocket!");

}

}

改变测试类(MiniDuckSimulator.java),加上模型鸭,并使模型鸭具有火箭动力。

public class MiniDuckSimulator {

public static void main(String[] args) {

Duck mallard = new MallardDuck();

mallard.performQuack();

mallard.performFly();

Duck model = new ModelDuck();

//第一次调用performFly() 会被委托给flyBehavior对象(也就是FlyNoWay对象),该对象是在模型鸭构造器中设置的。

model.performFly();

//这会调用继承来的setter 方法,把火箭动力飞行的行为设定到模型鸭中。哇咧! 模型鸭突然具有火箭动力飞行能力。

model.setFlyBehavior(new FlyRocketPowered());

//如果成功了, 就意味着模型鸭动态地改变行为。如果把行为的实现绑死在鸭子类中, 可就无法做到这样。

model.performFly();

}

}

运行一下,看下结果

I’m a real Mallard duck

Quack

I’m flying!!

I’m a model duck

I can’t fly

I’m flying with a rocket!

如同本例一般,当你将两个类结合起来使用,这就是组合(composition)。这种作法和『继承』不同的地方在于,

鸭子的行为不是继承而来,而是和适当的行为对象『组合』而来。

这是一个很重要的技巧。其实是使用了策略模式中的第三个设计原则, 多用组合,少用继承。

现在来总结一下,鸭子的行为被放在分开的类中,此类专门提供某行为的实现。

这样,鸭子类就不再需要知道行为的实现细节。

鸭子类不会负责实现Flyable与Quackable接口,反而是由其他类专门实现FlyBehavior与QuackBehavior,

这就称为「行为」类。由行为类实现行为接口,而不是由Duck类实现行为接口。

这样的作法迥异于以往,行为不再是由继承Duck超类的具体实现而来, 或是继承某个接口并由子类自行实现而来。

(这两种作法都是依赖于「实现」, 我们被实现绑得死死的, 没办法更改行为,除非写更多代码)。

在我们的新设计中, 鸭子的子类使用接口( FlyBehavior与QuackBehavior)所表示的行为,所以实际的实现不会被

绑死在鸭子的子类中。( 换句话说, 特定的实现代码位于实现FlyBehavior与QuakcBehavior的特定类中),这样我们就获得了更大的灵活性和可扩展性。

一道java题

我建议你还是先好好学习java的基础,让后再看代码,protected FlyBehavior (3); 是创建一个名字为(3)的对象。我想告诉你这个以后,别的都不用说了吧。因为4更3一样。5和6就是对象调用自己的方法了。

Java的题目有点急!

package com.test;

public class Duck extends Animal {

private String name;

public String getName() {

return name;

}

public void shout() {

System.out.println("嘎嘎嘎……");

}

public Duck(String name) {

super();

this.name = name;

}

}

package com.test;

public class Cat extends Animal {

private String name;

public void shout() {

System.out.println("喵喵喵……");

}

public Cat(String name) {

super();

this.name = name;

}

public String getName() {

return name;

}

}

package com.test;

public class Dolphin extends Animal {

private String name;

public Dolphin(String name) {

super();

this.name = name;

}

public void shout() {

System.out.println("海豚音……");

}

public String getName() {

return name;

}

}

package com.test;

public abstract class Animal implements Bark{

}

package com.test;

public interface Bark {

void shout();

}

package com.test;

public class Test {

public static void main(String[] args) {

System.out.println("动物名\t动物叫");

// 多态体现

Animal duck = new Duck("唐老鸭");

System.out.print(((Duck) duck).getName() + "\t");

duck.shout();

Animal cat = new Cat("加菲猫");

System.out.print(((Cat) cat).getName() + "\t");

cat.shout();

Animal dolphin = new Dolphin("海豚奇奇");

System.out.print(((Dolphin) dolphin).getName() + "\t");

dolphin.shout();

System.out.println("\n动物名\t腿的条数\t动物叫");

Animal[] animals = new Animal[3];

animals[0] = duck;

animals[1] = cat;

animals[2] = dolphin;

for (Animal animal : animals) {

if (animal instanceof Duck) {

System.out.print(((Duck) animal).getName() + "\t2\t");

animal.shout();

} else if (animal instanceof Cat) {

System.out.print(((Cat) animal).getName() + "\t4\t");

animal.shout();

} else {

System.out.print(((Dolphin) animal).getName() + "\t4\t");

animal.shout();

}

}

}

}

简单写了下

编写动物乐园java,满意会加分的!!!

public class Animal

{

public String name;

public int legs;

public String sound;

public Animal(String name, int legs, String sound){

this.name = name;

this.legs = legs;

this.sound = sound;

}

public String toString(){

return name + "\t" + legs + "\t" + sound;

}

public static void main(String[]args)

{

//init

Animal[] animals = new Animal[3];

animals[0] = new Animal("加菲猫",4, "喵喵喵");

animals[1] = new Animal("唐小鸭",2, "嘎嘎嘎");

animals[2] = new Animal("海豚奇奇",0, "海豚音");

byte[] b = new byte[1024];

String[] names = {"猫", "鸭子", "海豚"};

int[] legs = {4,2,0};

String name;

int leg;

String sound;

while(true){

try{

System.out.println("动物名称\t腿的条数\t动物叫");

for (int i = 0; i  animals.length; i++) {

System.out.println(animals[i].toString());

}

System.out.println("0-修改,其他数字-退出");

int n = System.in.read(b);

String s = new String(b,0,n);

int oper = Integer.parseInt(s.trim());

if (oper != 0) {

System.out.println("退出!");

return;

}

for (int i = 0; i  animals.length; i++) {

System.out.println("请输入"+names[i]+"的名字");

n = System.in.read(b);

s = new String(b,0,n);

name = s.trim();

if (name.length() == 0) {

throw new Exception(names[i]+"必须有名字");

}

System.out.println("请输入"+names[i]+"的腿数");

n = System.in.read(b);

s = new String(b,0,n);

leg = Integer.parseInt(s.trim());

if (leg != legs[i]) {

throw new Exception(names[i]+"必须有"+legs[i]+"条腿");

}

System.out.println("请输入"+names[i]+"的叫声");

n = System.in.read(b);

s = new String(b,0,n);

sound = s.trim();

if (sound.length() == 0) {

throw new Exception(names[i]+"必须有声音");

}

animals[i].name = name;

animals[i].legs = leg;

animals[i].sound = sound;

}

}

catch(Exception e){

e.printStackTrace();

}

}

}

}

凑合写的....

instanceof 不难吧...就是验证类是否为类或者父类的实例...

我看你ppt要求的是自定义异常抛出,接口继承应该很简单,抛出异常参考我的代码即可..

用JAVA 编写以下程序

假设鸡有a只,兔有b只。则可计算得出:

b=f/2-h

a=2h-f/2

从而在f.h为正整数的前提下f和h的条件为:

4h=f=2h

f%2==0

具体程序内容如下

void main()

{

int a=0,b=0,f,h;

bool logo=ture;

cout"请输入鸡和鸭的数目,用空格隔开:/n";

while(logo)

{

cinfh;

if(f%2!=0||f2*h||f4*h)

{

cout"输入数据错误!请重新输入!/n";

}

else

{

a=2*h-f/2;

b=f/2-h;

cout"鸡的数目为:"a"/n鸭的数目为:"b"/n";

logo=false;

}

}

}


网站名称:java小黄鸭代码 程序小黄鸭
文章转载:http://cdxtjz.cn/article/hidige.html

其他资讯